Make all handlers objects refcounted.

I'm realizing that basically all upb objects
will need to be refcounted to be sharable
across languages, but *not* messages which
are on their way out so we can get out of
the business of data representations.

Things which must be refcounted:
- encoders, decoders
- handlers objects
- defs
pull/13171/head
Joshua Haberman 14 years ago
parent 2ccebb74c3
commit a503b8859c
  1. 8
      benchmarks/parsestream.upb_table.c
  2. 8
      benchmarks/parsetostruct.upb_table.c
  3. 4
      src/upb.h
  4. 52
      src/upb_atomic.h
  5. 2
      src/upb_decoder.c
  6. 12
      src/upb_decoder_x86.dasc
  7. 10
      src/upb_def.c
  8. 8
      src/upb_def.h
  9. 24
      src/upb_glue.c
  10. 76
      src/upb_handlers.c
  11. 155
      src/upb_handlers.h
  12. 12
      src/upb_msg.c
  13. 4
      src/upb_msg.h
  14. 2
      src/upb_string.c
  15. 2
      src/upb_string.h
  16. 8
      tests/tests.c

@ -10,7 +10,6 @@ static upb_string *input_str;
static upb_msgdef *def; static upb_msgdef *def;
static upb_decoder decoder; static upb_decoder decoder;
static upb_stringsrc stringsrc; static upb_stringsrc stringsrc;
upb_handlers handlers;
static upb_sflow_t startsubmsg(void *_m, upb_value fval) { static upb_sflow_t startsubmsg(void *_m, upb_value fval) {
(void)_m; (void)_m;
@ -61,11 +60,12 @@ static bool initialize()
return false; return false;
} }
upb_handlers_init(&handlers); upb_handlers *handlers = upb_handlers_new();
// Cause all messages to be read, but do nothing when they are. // Cause all messages to be read, but do nothing when they are.
upb_handlerset hset = {NULL, NULL, value, startsubmsg, NULL, NULL, NULL}; upb_handlerset hset = {NULL, NULL, value, startsubmsg, NULL, NULL, NULL};
upb_handlers_reghandlerset(&handlers, def, &hset); upb_handlers_reghandlerset(handlers, def, &hset);
upb_decoder_init(&decoder, &handlers); upb_decoder_init(&decoder, handlers);
upb_handlers_unref(handlers);
upb_stringsrc_init(&stringsrc); upb_stringsrc_init(&stringsrc);
return true; return true;
} }

@ -12,7 +12,6 @@ static upb_msgdef *def;
static upb_msg *msg; static upb_msg *msg;
static upb_stringsrc strsrc; static upb_stringsrc strsrc;
static upb_decoder d; static upb_decoder d;
static upb_handlers h;
static bool initialize() static bool initialize()
{ {
@ -53,9 +52,10 @@ static bool initialize()
msg = upb_msg_new(def); msg = upb_msg_new(def);
upb_stringsrc_init(&strsrc); upb_stringsrc_init(&strsrc);
upb_handlers_init(&h); upb_handlers *handlers = upb_handlers_new();
upb_msg_reghandlers(&h, def); upb_msg_reghandlers(handlers, def);
upb_decoder_init(&d, &h); upb_decoder_init(&d, handlers);
upb_handlers_unref(handlers);
if (!BYREF) { if (!BYREF) {
// Pretend the input string is stack-allocated, which will force its data // Pretend the input string is stack-allocated, which will force its data

@ -162,7 +162,7 @@ typedef struct {
upb_bytesrc *bytesrc; upb_bytesrc *bytesrc;
upb_msg *msg; upb_msg *msg;
upb_array *arr; upb_array *arr;
upb_atomic_refcount_t *refcount; upb_atomic_t *refcount;
upb_fielddef *fielddef; upb_fielddef *fielddef;
void *_void; void *_void;
} val; } val;
@ -204,7 +204,7 @@ UPB_VALUE_ACCESSORS(fielddef, fielddef, upb_fielddef*, UPB_VALUETYPE_FIELDDEF);
extern upb_value UPB_NO_VALUE; extern upb_value UPB_NO_VALUE;
INLINE upb_atomic_refcount_t *upb_value_getrefcount(upb_value val) { INLINE upb_atomic_t *upb_value_getrefcount(upb_value val) {
assert(val.type == UPB_TYPE(MESSAGE) || assert(val.type == UPB_TYPE(MESSAGE) ||
val.type == UPB_TYPE(STRING) || val.type == UPB_TYPE(STRING) ||
val.type == UPB_VALUETYPE_ARRAY); val.type == UPB_VALUETYPE_ARRAY);

@ -39,35 +39,19 @@ extern "C" {
typedef struct { typedef struct {
int v; int v;
} upb_atomic_refcount_t; } upb_atomic_t;
INLINE void upb_atomic_refcount_init(upb_atomic_refcount_t *a, int val) { #define UPB_ATOMIC_INIT(x) {x}
a->v = val;
}
INLINE bool upb_atomic_ref(upb_atomic_refcount_t *a) {
return a->v++ == 0;
}
INLINE bool upb_atomic_unref(upb_atomic_refcount_t *a) {
return --a->v == 0;
}
INLINE int upb_atomic_read(upb_atomic_refcount_t *a) { INLINE void upb_atomic_init(upb_atomic_t *a, int val) { a->v = val; }
return a->v; INLINE bool upb_atomic_ref(upb_atomic_t *a) { return a->v++ == 0; }
} INLINE bool upb_atomic_unref(upb_atomic_t *a) { return --a->v == 0; }
INLINE int upb_atomic_read(upb_atomic_t *a) { return a->v; }
INLINE bool upb_atomic_add(upb_atomic_refcount_t *a, int val) { INLINE bool upb_atomic_add(upb_atomic_t *a, int val) {
a->v += val; a->v += val;
return a->v == 0; return a->v == 0;
} }
INLINE int upb_atomic_fetch_and_add(upb_atomic_refcount_t *a, int val) {
int ret = a->v;
a->v += val;
return ret;
}
#endif #endif
/* Atomic refcount ************************************************************/ /* Atomic refcount ************************************************************/
@ -82,26 +66,26 @@ INLINE int upb_atomic_fetch_and_add(upb_atomic_refcount_t *a, int val) {
typedef struct { typedef struct {
volatile int v; volatile int v;
} upb_atomic_refcount_t; } upb_atomic_t;
INLINE void upb_atomic_refcount_init(upb_atomic_refcount_t *a, int val) { INLINE void upb_atomic_init(upb_atomic_t *a, int val) {
a->v = val; a->v = val;
__sync_synchronize(); /* Ensure the initialized value is visible. */ __sync_synchronize(); /* Ensure the initialized value is visible. */
} }
INLINE bool upb_atomic_ref(upb_atomic_refcount_t *a) { INLINE bool upb_atomic_ref(upb_atomic_t *a) {
return __sync_fetch_and_add(&a->v, 1) == 0; return __sync_fetch_and_add(&a->v, 1) == 0;
} }
INLINE bool upb_atomic_add(upb_atomic_refcount_t *a, int n) { INLINE bool upb_atomic_add(upb_atomic_t *a, int n) {
return __sync_add_and_fetch(&a->v, n) == 0; return __sync_add_and_fetch(&a->v, n) == 0;
} }
INLINE bool upb_atomic_unref(upb_atomic_refcount_t *a) { INLINE bool upb_atomic_unref(upb_atomic_t *a) {
return __sync_sub_and_fetch(&a->v, 1) == 0; return __sync_sub_and_fetch(&a->v, 1) == 0;
} }
INLINE bool upb_atomic_read(upb_atomic_refcount_t *a) { INLINE bool upb_atomic_read(upb_atomic_t *a) {
return __sync_fetch_and_add(&a->v, 0); return __sync_fetch_and_add(&a->v, 0);
} }
@ -112,17 +96,17 @@ INLINE bool upb_atomic_read(upb_atomic_refcount_t *a) {
typedef struct { typedef struct {
volatile LONG val; volatile LONG val;
} upb_atomic_refcount_t; } upb_atomic_t;
INLINE void upb_atomic_refcount_init(upb_atomic_refcount_t *a, int val) { INLINE void upb_atomic_init(upb_atomic_t *a, int val) {
InterlockedExchange(&a->val, val); InterlockedExchange(&a->val, val);
} }
INLINE bool upb_atomic_ref(upb_atomic_refcount_t *a) { INLINE bool upb_atomic_ref(upb_atomic_t *a) {
return InterlockedIncrement(&a->val) == 1; return InterlockedIncrement(&a->val) == 1;
} }
INLINE bool upb_atomic_unref(upb_atomic_refcount_t *a) { INLINE bool upb_atomic_unref(upb_atomic_t *a) {
return InterlockedDecrement(&a->val) == 0; return InterlockedDecrement(&a->val) == 0;
} }
@ -131,7 +115,7 @@ INLINE bool upb_atomic_unref(upb_atomic_refcount_t *a) {
Implement them or compile with UPB_THREAD_UNSAFE. Implement them or compile with UPB_THREAD_UNSAFE.
#endif #endif
INLINE bool upb_atomic_only(upb_atomic_refcount_t *a) { INLINE bool upb_atomic_only(upb_atomic_t *a) {
return upb_atomic_read(a) == 1; return upb_atomic_read(a) == 1;
} }

@ -399,10 +399,10 @@ void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc, void *closure) {
} }
void upb_decoder_uninit(upb_decoder *d) { void upb_decoder_uninit(upb_decoder *d) {
upb_dispatcher_uninit(&d->dispatcher);
upb_string_unref(d->bufstr); upb_string_unref(d->bufstr);
upb_string_unref(d->tmp); upb_string_unref(d->tmp);
#ifdef UPB_USE_JIT_X64 #ifdef UPB_USE_JIT_X64
if (d->dispatcher.handlers->should_jit) upb_decoder_freejit(d); if (d->dispatcher.handlers->should_jit) upb_decoder_freejit(d);
#endif #endif
upb_dispatcher_uninit(&d->dispatcher);
} }

@ -286,7 +286,7 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
| jne ->exit_jit // In the future: could be an unknown field or packed. | jne ->exit_jit // In the future: could be an unknown field or packed.
|=>f->jit_pclabel_notypecheck: |=>f->jit_pclabel_notypecheck:
if (f->repeated) { if (f->repeated) {
if (f->startseq != upb_startfield_nop) { if (f->startseq) {
| mov ARG1_64, CLOSURE | mov ARG1_64, CLOSURE
| loadfval f | loadfval f
| callp f->startseq | callp f->startseq
@ -394,7 +394,7 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
// Call callbacks. // Call callbacks.
if (upb_issubmsgtype(f->type)) { if (upb_issubmsgtype(f->type)) {
// Call startsubmsg handler (if any). // Call startsubmsg handler (if any).
if (f->startsubmsg != upb_startfield_nop) { if (f->startsubmsg) {
// upb_sflow_t startsubmsg(void *closure, upb_value fval) // upb_sflow_t startsubmsg(void *closure, upb_value fval)
| mov r12d, ARG3_32 | mov r12d, ARG3_32
| callp f->startsubmsg | callp f->startsubmsg
@ -423,7 +423,7 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
| popframe | popframe
// Call endsubmsg handler (if any). // Call endsubmsg handler (if any).
if (f->endsubmsg != upb_endfield_nop) { if (f->endsubmsg) {
// upb_flow_t endsubmsg(void *closure, upb_value fval); // upb_flow_t endsubmsg(void *closure, upb_value fval);
| mov ARG1_64, CLOSURE | mov ARG1_64, CLOSURE
| loadfval f | loadfval f
@ -441,7 +441,7 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
| checktag tag | checktag tag
| je <1 | je <1
| popframe | popframe
if (f->endseq != upb_endfield_nop) { if (f->endseq) {
| mov ARG1_64, CLOSURE | mov ARG1_64, CLOSURE
| loadfval f | loadfval f
| callp f->endseq | callp f->endseq
@ -466,7 +466,7 @@ static int upb_compare_uint32(const void *a, const void *b) {
static void upb_decoder_jit_msg(upb_decoder *d, upb_mhandlers *m) { static void upb_decoder_jit_msg(upb_decoder *d, upb_mhandlers *m) {
|=>m->jit_startmsg_pclabel: |=>m->jit_startmsg_pclabel:
// Call startmsg handler (if any): // Call startmsg handler (if any):
if (m->startmsg != upb_startmsg_nop) { if (m->startmsg) {
// upb_flow_t startmsg(void *closure); // upb_flow_t startmsg(void *closure);
| mov ARG1_64, FRAME->closure | mov ARG1_64, FRAME->closure
| callp m->startmsg | callp m->startmsg
@ -520,7 +520,7 @@ static void upb_decoder_jit_msg(upb_decoder *d, upb_mhandlers *m) {
|=>m->jit_endofmsg_pclabel: |=>m->jit_endofmsg_pclabel:
// We are at end-of-submsg: call endmsg handler (if any): // We are at end-of-submsg: call endmsg handler (if any):
if (m->endmsg != upb_endmsg_nop) { if (m->endmsg) {
// void endmsg(void *closure, upb_status *status) { // void endmsg(void *closure, upb_status *status) {
| mov ARG1_64, FRAME->closure | mov ARG1_64, FRAME->closure
| lea ARG2_64, DECODER->dispatcher.status | lea ARG2_64, DECODER->dispatcher.status

@ -172,7 +172,7 @@ static void upb_def_init(upb_def *def, upb_deftype type) {
def->is_cyclic = 0; // We detect this later, after resolving refs. def->is_cyclic = 0; // We detect this later, after resolving refs.
def->search_depth = 0; def->search_depth = 0;
def->fqname = NULL; def->fqname = NULL;
upb_atomic_refcount_init(&def->refcount, 1); upb_atomic_init(&def->refcount, 1);
} }
static void upb_def_uninit(upb_def *def) { static void upb_def_uninit(upb_def *def) {
@ -868,7 +868,7 @@ static upb_flow_t upb_msgdef_startmsg(void *_b) {
upb_defbuilder *b = _b; upb_defbuilder *b = _b;
upb_msgdef *m = malloc(sizeof(*m)); upb_msgdef *m = malloc(sizeof(*m));
upb_def_init(&m->base, UPB_DEF_MSG); upb_def_init(&m->base, UPB_DEF_MSG);
upb_atomic_refcount_init(&m->cycle_refcount, 0); upb_atomic_init(&m->cycle_refcount, 0);
upb_inttable_init(&m->itof, 4, sizeof(upb_itof_ent)); upb_inttable_init(&m->itof, 4, sizeof(upb_itof_ent));
upb_strtable_init(&m->ntof, 4, sizeof(upb_ntof_ent)); upb_strtable_init(&m->ntof, 4, sizeof(upb_ntof_ent));
m->default_message = NULL; m->default_message = NULL;
@ -898,7 +898,7 @@ static void upb_msgdef_endmsg(void *_b, upb_status *status) {
// Assign offsets in the msg. // Assign offsets in the msg.
m->set_flags_bytes = upb_div_round_up(n, 8); m->set_flags_bytes = upb_div_round_up(n, 8);
m->size = sizeof(upb_atomic_refcount_t) + m->set_flags_bytes; m->size = sizeof(upb_atomic_t) + m->set_flags_bytes;
size_t max_align = 0; size_t max_align = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
@ -926,7 +926,7 @@ static void upb_msgdef_endmsg(void *_b, upb_status *status) {
// whole must be a multiple of the greatest alignment of any member. // whole must be a multiple of the greatest alignment of any member.
size_t offset = upb_align_up(m->size, align); size_t offset = upb_align_up(m->size, align);
// Offsets are relative to the end of the refcount. // Offsets are relative to the end of the refcount.
f->byte_offset = offset - sizeof(upb_atomic_refcount_t); f->byte_offset = offset - sizeof(upb_atomic_t);
m->size = offset + size; m->size = offset + size;
max_align = UPB_MAX(max_align, align); max_align = UPB_MAX(max_align, align);
} }
@ -1242,7 +1242,7 @@ err:
upb_symtab *upb_symtab_new() upb_symtab *upb_symtab_new()
{ {
upb_symtab *s = malloc(sizeof(*s)); upb_symtab *s = malloc(sizeof(*s));
upb_atomic_refcount_init(&s->refcount, 1); upb_atomic_init(&s->refcount, 1);
upb_rwlock_init(&s->lock); upb_rwlock_init(&s->lock);
upb_strtable_init(&s->symtab, 16, sizeof(upb_symtab_ent)); upb_strtable_init(&s->symtab, 16, sizeof(upb_symtab_ent));
s->fds_msgdef = NULL; s->fds_msgdef = NULL;

@ -56,7 +56,7 @@ typedef int8_t upb_deftype_t;
typedef struct { typedef struct {
upb_string *fqname; // Fully qualified. upb_string *fqname; // Fully qualified.
upb_atomic_refcount_t refcount; upb_atomic_t refcount;
upb_deftype_t type; upb_deftype_t type;
// The is_cyclic flag could go in upb_msgdef instead of here, because only // The is_cyclic flag could go in upb_msgdef instead of here, because only
@ -110,7 +110,7 @@ struct _upb_fielddef {
// For the case of an enum or a submessage, points to the def for that type. // For the case of an enum or a submessage, points to the def for that type.
upb_def *def; upb_def *def;
upb_atomic_refcount_t refcount; upb_atomic_t refcount;
}; };
// A variety of tests about the type of a field. // A variety of tests about the type of a field.
@ -159,7 +159,7 @@ INLINE bool upb_elem_ismm(upb_fielddef *f) {
// Structure that describes a single .proto message type. // Structure that describes a single .proto message type.
typedef struct _upb_msgdef { typedef struct _upb_msgdef {
upb_def base; upb_def base;
upb_atomic_refcount_t cycle_refcount; upb_atomic_t cycle_refcount;
uint32_t size; uint32_t size;
uint32_t set_flags_bytes; uint32_t set_flags_bytes;
@ -283,7 +283,7 @@ INLINE int32_t upb_enum_iter_number(upb_enum_iter iter) {
// Clients add definitions to the symtab by supplying descriptors (as defined // Clients add definitions to the symtab by supplying descriptors (as defined
// in descriptor.proto) via the upb_stream interface. // in descriptor.proto) via the upb_stream interface.
struct _upb_symtab { struct _upb_symtab {
upb_atomic_refcount_t refcount; upb_atomic_t refcount;
upb_rwlock_t lock; // Protects all members except the refcount. upb_rwlock_t lock; // Protects all members except the refcount.
upb_strtable symtab; // The symbol table. upb_strtable symtab; // The symbol table.
upb_msgdef *fds_msgdef; // Msgdef for google.protobuf.FileDescriptorSet. upb_msgdef *fds_msgdef; // Msgdef for google.protobuf.FileDescriptorSet.

@ -17,13 +17,13 @@ void upb_strtomsg(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_stringsrc_init(&strsrc); upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str); upb_stringsrc_reset(&strsrc, str);
upb_handlers h; upb_handlers *h = upb_handlers_new();
upb_handlers_init(&h); upb_msg_reghandlers(h, md);
upb_msg_reghandlers(&h, md);
upb_decoder d; upb_decoder d;
upb_decoder_init(&d, &h); upb_decoder_init(&d, h);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), msg); upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), msg);
upb_handlers_unref(h);
upb_decoder_decode(&d, status); upb_decoder_decode(&d, status);
@ -38,13 +38,12 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_stringsink_reset(&strsink, str); upb_stringsink_reset(&strsink, str);
upb_textprinter *p = upb_textprinter_new(); upb_textprinter *p = upb_textprinter_new();
upb_handlers h; upb_handlers *h = upb_handlers_new();
upb_handlers_init(&h); upb_textprinter_reghandlers(h, md);
upb_textprinter_reghandlers(&h, md);
upb_textprinter_reset(p, upb_stringsink_bytesink(&strsink), single_line); upb_textprinter_reset(p, upb_stringsink_bytesink(&strsink), single_line);
upb_status status = UPB_STATUS_INIT; upb_status status = UPB_STATUS_INIT;
upb_msg_runhandlers(msg, md, &h, p, &status); upb_msg_runhandlers(msg, md, h, p, &status);
// None of {upb_msg_runhandlers, upb_textprinter, upb_stringsink} should be // None of {upb_msg_runhandlers, upb_textprinter, upb_stringsink} should be
// capable of returning an error. // capable of returning an error.
assert(upb_ok(&status)); assert(upb_ok(&status));
@ -52,6 +51,7 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_stringsink_uninit(&strsink); upb_stringsink_uninit(&strsink);
upb_textprinter_free(p); upb_textprinter_free(p);
upb_handlers_unref(h);
} }
void upb_parsedesc(upb_symtab *symtab, upb_string *str, upb_status *status) { void upb_parsedesc(upb_symtab *symtab, upb_string *str, upb_status *status) {
@ -59,12 +59,12 @@ void upb_parsedesc(upb_symtab *symtab, upb_string *str, upb_status *status) {
upb_stringsrc_init(&strsrc); upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str); upb_stringsrc_reset(&strsrc, str);
upb_handlers h; upb_handlers *h = upb_handlers_new();
upb_handlers_init(&h); upb_defbuilder_reghandlers(h);
upb_defbuilder_reghandlers(&h);
upb_decoder d; upb_decoder d;
upb_decoder_init(&d, &h); upb_decoder_init(&d, h);
upb_handlers_unref(h);
upb_defbuilder *b = upb_defbuilder_new(symtab); upb_defbuilder *b = upb_defbuilder_new(symtab);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), b); upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), b);

@ -9,42 +9,13 @@
#include "upb_handlers.h" #include "upb_handlers.h"
upb_flow_t upb_startmsg_nop(void *closure) {
(void)closure;
return UPB_CONTINUE;
}
void upb_endmsg_nop(void *closure, upb_status *status) {
(void)closure;
(void)status;
}
upb_flow_t upb_value_nop(void *closure, upb_value fval, upb_value val) {
(void)closure;
(void)fval;
(void)val;
return UPB_CONTINUE;
}
upb_sflow_t upb_startfield_nop(void *closure, upb_value fval) {
(void)fval;
return UPB_CONTINUE_WITH(closure);
}
upb_flow_t upb_endfield_nop(void *closure, upb_value fval) {
(void)closure;
(void)fval;
return UPB_CONTINUE;
}
/* upb_mhandlers **************************************************************/ /* upb_mhandlers **************************************************************/
static upb_mhandlers *upb_mhandlers_new() { static upb_mhandlers *upb_mhandlers_new() {
upb_mhandlers *m = malloc(sizeof(*m)); upb_mhandlers *m = malloc(sizeof(*m));
upb_inttable_init(&m->fieldtab, 8, sizeof(upb_fhandlers)); upb_inttable_init(&m->fieldtab, 8, sizeof(upb_fhandlers));
m->startmsg = &upb_startmsg_nop; m->startmsg = NULL;
m->endmsg = &upb_endmsg_nop; m->endmsg = NULL;
m->tablearray = NULL; m->tablearray = NULL;
m->is_group = false; m->is_group = false;
return m; return m;
@ -57,11 +28,8 @@ static upb_fhandlers *_upb_mhandlers_newfhandlers(upb_mhandlers *m, uint32_t n,
upb_fhandlers *f = upb_inttable_lookup(&m->fieldtab, tag); upb_fhandlers *f = upb_inttable_lookup(&m->fieldtab, tag);
if (f) abort(); if (f) abort();
upb_fhandlers new_f = {false, type, repeated, upb_fhandlers new_f = {false, type, repeated,
repeated && upb_isprimitivetype(type), n, m, NULL, UPB_NO_VALUE, repeated && upb_isprimitivetype(type), UPB_ATOMIC_INIT(0),
&upb_value_nop, n, m, NULL, UPB_NO_VALUE, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, NULL};
&upb_startfield_nop, &upb_endfield_nop,
&upb_startfield_nop, &upb_endfield_nop,
0, 0, 0, NULL};
upb_inttable_insert(&m->fieldtab, tag, &new_f); upb_inttable_insert(&m->fieldtab, tag, &new_f);
f = upb_inttable_lookup(&m->fieldtab, tag); f = upb_inttable_lookup(&m->fieldtab, tag);
assert(f); assert(f);
@ -92,14 +60,20 @@ upb_fhandlers *upb_mhandlers_newfhandlers_subm(upb_mhandlers *m, uint32_t n,
/* upb_handlers ***************************************************************/ /* upb_handlers ***************************************************************/
void upb_handlers_init(upb_handlers *h) { upb_handlers *upb_handlers_new() {
upb_handlers *h = malloc(sizeof(*h));
upb_atomic_init(&h->refcount, 1);
h->msgs_len = 0; h->msgs_len = 0;
h->msgs_size = 4; h->msgs_size = 4;
h->msgs = malloc(h->msgs_size * sizeof(*h->msgs)); h->msgs = malloc(h->msgs_size * sizeof(*h->msgs));
h->should_jit = true; h->should_jit = true;
return h;
} }
void upb_handlers_uninit(upb_handlers *h) { void upb_handlers_ref(upb_handlers *h) { upb_atomic_ref(&h->refcount); }
void upb_handlers_unref(upb_handlers *h) {
if (upb_atomic_unref(&h->refcount)) {
for (int i = 0; i < h->msgs_len; i++) { for (int i = 0; i < h->msgs_len; i++) {
upb_mhandlers *mh = h->msgs[i]; upb_mhandlers *mh = h->msgs[i];
upb_inttable_free(&mh->fieldtab); upb_inttable_free(&mh->fieldtab);
@ -107,6 +81,8 @@ void upb_handlers_uninit(upb_handlers *h) {
free(mh); free(mh);
} }
free(h->msgs); free(h->msgs);
free(h);
}
} }
upb_mhandlers *upb_handlers_newmhandlers(upb_handlers *h) { upb_mhandlers *upb_handlers_newmhandlers(upb_handlers *h) {
@ -172,7 +148,7 @@ upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m,
/* upb_dispatcher *************************************************************/ /* upb_dispatcher *************************************************************/
static upb_fhandlers toplevel_f = { static upb_fhandlers toplevel_f = {
false, UPB_TYPE(GROUP), false, false, 0, false, UPB_TYPE(GROUP), false, false, UPB_ATOMIC_INIT(0), 0,
NULL, NULL, // submsg NULL, NULL, // submsg
#ifdef NDEBUG #ifdef NDEBUG
{{0}}, {{0}},
@ -185,6 +161,7 @@ void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h,
upb_skip_handler *skip, upb_exit_handler *exit, upb_skip_handler *skip, upb_exit_handler *exit,
void *srcclosure) { void *srcclosure) {
d->handlers = h; d->handlers = h;
upb_handlers_ref(h);
for (int i = 0; i < h->msgs_len; i++) { for (int i = 0; i < h->msgs_len; i++) {
upb_mhandlers *m = h->msgs[i]; upb_mhandlers *m = h->msgs[i];
upb_inttable_compact(&m->fieldtab); upb_inttable_compact(&m->fieldtab);
@ -207,18 +184,19 @@ upb_dispatcher_frame *upb_dispatcher_reset(upb_dispatcher *d, void *closure) {
} }
void upb_dispatcher_uninit(upb_dispatcher *d) { void upb_dispatcher_uninit(upb_dispatcher *d) {
upb_handlers_uninit(d->handlers); upb_handlers_unref(d->handlers);
upb_status_uninit(&d->status); upb_status_uninit(&d->status);
} }
void upb_dispatch_startmsg(upb_dispatcher *d) { void upb_dispatch_startmsg(upb_dispatcher *d) {
upb_flow_t flow = d->msgent->startmsg(d->top->closure); upb_flow_t flow = UPB_CONTINUE;
if (d->msgent->startmsg) d->msgent->startmsg(d->top->closure);
if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow); if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow);
} }
void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status) { void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status) {
assert(d->top == d->stack); assert(d->top == d->stack);
d->msgent->endmsg(d->top->closure, &d->status); if (d->msgent->endmsg) d->msgent->endmsg(d->top->closure, &d->status);
// TODO: should we avoid this copy by passing client's status obj to cbs? // TODO: should we avoid this copy by passing client's status obj to cbs?
upb_copyerr(status, &d->status); upb_copyerr(status, &d->status);
} }
@ -241,7 +219,8 @@ upb_dispatcher_frame *upb_dispatch_startseq(upb_dispatcher *d,
return d->top; // Dummy. return d->top; // Dummy.
} }
upb_sflow_t sflow = f->startseq(d->top->closure, f->fval); upb_sflow_t sflow = UPB_CONTINUE_WITH(d->top->closure);
if (f->startseq) sflow = f->startseq(d->top->closure, f->fval);
if (sflow.flow != UPB_CONTINUE) { if (sflow.flow != UPB_CONTINUE) {
_upb_dispatcher_unwind(d, sflow.flow); _upb_dispatcher_unwind(d, sflow.flow);
return d->top; // Dummy. return d->top; // Dummy.
@ -261,7 +240,8 @@ upb_dispatcher_frame *upb_dispatch_endseq(upb_dispatcher *d) {
assert(d->top->is_sequence); assert(d->top->is_sequence);
upb_fhandlers *f = d->top->f; upb_fhandlers *f = d->top->f;
--d->top; --d->top;
upb_flow_t flow = f->endseq(d->top->closure, f->fval); upb_flow_t flow = UPB_CONTINUE;
if (f->endseq) flow = f->endseq(d->top->closure, f->fval);
if (flow != UPB_CONTINUE) { if (flow != UPB_CONTINUE) {
printf("YO, UNWINDING!\n"); printf("YO, UNWINDING!\n");
_upb_dispatcher_unwind(d, flow); _upb_dispatcher_unwind(d, flow);
@ -282,7 +262,8 @@ upb_dispatcher_frame *upb_dispatch_startsubmsg(upb_dispatcher *d,
return d->top; // Dummy. return d->top; // Dummy.
} }
upb_sflow_t sflow = f->startsubmsg(d->top->closure, f->fval); upb_sflow_t sflow = UPB_CONTINUE_WITH(d->top->closure);
if (f->startsubmsg) sflow = f->startsubmsg(d->top->closure, f->fval);
if (sflow.flow != UPB_CONTINUE) { if (sflow.flow != UPB_CONTINUE) {
_upb_dispatcher_unwind(d, sflow.flow); _upb_dispatcher_unwind(d, sflow.flow);
return d->top; // Dummy. return d->top; // Dummy.
@ -304,11 +285,12 @@ upb_dispatcher_frame *upb_dispatch_endsubmsg(upb_dispatcher *d) {
assert(d->top > d->stack); assert(d->top > d->stack);
assert(!d->top->is_sequence); assert(!d->top->is_sequence);
upb_fhandlers *f = d->top->f; upb_fhandlers *f = d->top->f;
d->msgent->endmsg(d->top->closure, &d->status); if (d->msgent->endmsg) d->msgent->endmsg(d->top->closure, &d->status);
d->msgent = d->top->f->msg; d->msgent = d->top->f->msg;
d->dispatch_table = &d->msgent->fieldtab; d->dispatch_table = &d->msgent->fieldtab;
--d->top; --d->top;
upb_flow_t flow = f->endsubmsg(d->top->closure, f->fval); upb_flow_t flow = UPB_CONTINUE;
if (f->endsubmsg) f->endsubmsg(d->top->closure, f->fval);
if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow); if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow);
return d->top; return d->top;
} }

@ -22,7 +22,7 @@
extern "C" { extern "C" {
#endif #endif
/* upb_handlers ***************************************************************/ /* Handlers protocol definition ***********************************************/
// A upb_handlers object represents a graph of handlers. Each message can have // A upb_handlers object represents a graph of handlers. Each message can have
// a set of handlers as well as a set of fields which themselves have handlers. // a set of handlers as well as a set of fields which themselves have handlers.
@ -106,49 +106,42 @@ typedef enum {
// TODO: Add UPB_SUSPEND, for resumable producers/consumers. // TODO: Add UPB_SUSPEND, for resumable producers/consumers.
} upb_flow_t; } upb_flow_t;
// The startsubmsg handler needs to also pass a closure to the submsg.
typedef struct {
upb_flow_t flow;
void *closure;
} upb_sflow_t;
INLINE upb_sflow_t UPB_SFLOW(upb_flow_t flow, void *closure) {
upb_sflow_t ret = {flow, closure};
return ret;
}
#define UPB_CONTINUE_WITH(c) UPB_SFLOW(UPB_CONTINUE, c)
#define UPB_SBREAK UPB_SFLOW(UPB_BREAK, NULL)
// Typedefs for all of the handler functions defined above. // Typedefs for all of the handler functions defined above.
typedef struct _upb_sflow upb_sflow_t;
typedef upb_flow_t (upb_startmsg_handler)(void *c); typedef upb_flow_t (upb_startmsg_handler)(void *c);
typedef void (upb_endmsg_handler)(void *c, upb_status *status); typedef void (upb_endmsg_handler)(void *c, upb_status *status);
typedef upb_flow_t (upb_value_handler)(void *c, upb_value fval, upb_value val); typedef upb_flow_t (upb_value_handler)(void *c, upb_value fval, upb_value val);
typedef upb_sflow_t (upb_startfield_handler)(void *closure, upb_value fval); typedef upb_sflow_t (upb_startfield_handler)(void *closure, upb_value fval);
typedef upb_flow_t (upb_endfield_handler)(void *closure, upb_value fval); typedef upb_flow_t (upb_endfield_handler)(void *closure, upb_value fval);
// No-op implementations of all of the above handlers. Use these instead of
// rolling your own -- the JIT can recognize these and optimize away the call.
upb_flow_t upb_startmsg_nop(void *closure);
void upb_endmsg_nop(void *closure, upb_status *status);
upb_flow_t upb_value_nop(void *closure, upb_value fval, upb_value val);
upb_sflow_t upb_startfield_nop(void *closure, upb_value fval);
upb_flow_t upb_endfield_nop(void *closure, upb_value fval);
// Structure definitions. Do not access any fields directly! Accessors are /* upb_fhandlers **************************************************************/
// provided for the fields that may be get/set.
typedef struct _upb_mhandlers {
upb_startmsg_handler *startmsg;
upb_endmsg_handler *endmsg;
upb_inttable fieldtab; // Maps field number -> upb_fhandlers.
uint32_t jit_startmsg_pclabel;
uint32_t jit_endofbuf_pclabel;
uint32_t jit_endofmsg_pclabel;
uint32_t jit_unknownfield_pclabel;
bool is_group;
int32_t jit_parent_field_done_pclabel;
uint32_t max_field_number;
// Currently keyed on field number. Could also try keying it
// on encoded or decoded tag, or on encoded field number.
void **tablearray;
} upb_mhandlers;
// A upb_fhandlers object represents the set of handlers associated with one
// specific message field.
struct _upb_decoder; struct _upb_decoder;
struct _upb_mhandlers;
typedef struct _upb_fieldent { typedef struct _upb_fieldent {
bool junk; bool junk;
upb_fieldtype_t type; upb_fieldtype_t type;
bool repeated; bool repeated;
bool is_repeated_primitive; bool is_repeated_primitive;
upb_atomic_t refcount;
uint32_t number; uint32_t number;
upb_mhandlers *msg; struct _upb_mhandlers *msg;
upb_mhandlers *submsg; // Must be set iff upb_issubmsgtype(type) == true. struct _upb_mhandlers *submsg; // Set iff upb_issubmsgtype(type) == true.
upb_value fval; upb_value fval;
upb_value_handler *value; upb_value_handler *value;
upb_startfield_handler *startsubmsg; upb_startfield_handler *startsubmsg;
@ -161,34 +154,50 @@ typedef struct _upb_fieldent {
void (*decode)(struct _upb_decoder *d, struct _upb_fieldent *f); void (*decode)(struct _upb_decoder *d, struct _upb_fieldent *f);
} upb_fhandlers; } upb_fhandlers;
struct _upb_handlers { // fhandlers are created as part of a upb_handlers instance, but can be ref'd
// Array of msgdefs, [0]=toplevel. // and unref'd to prolong the life of the handlers.
upb_mhandlers **msgs; void upb_fhandlers_ref(upb_fhandlers *m);
int msgs_len, msgs_size; void upb_fhandlers_unref(upb_fhandlers *m);
bool should_jit;
};
typedef struct _upb_handlers upb_handlers;
void upb_handlers_init(upb_handlers *h); // upb_fhandlers accessors
void upb_handlers_uninit(upb_handlers *h); #define UPB_FHANDLERS_ACCESSORS(name, type) \
INLINE void upb_fhandlers_set ## name(upb_fhandlers *f, type v){f->name = v;} \
INLINE type upb_fhandlers_get ## name(upb_fhandlers *f) { return f->name; }
UPB_FHANDLERS_ACCESSORS(fval, upb_value)
UPB_FHANDLERS_ACCESSORS(value, upb_value_handler*)
UPB_FHANDLERS_ACCESSORS(startsubmsg, upb_startfield_handler*)
UPB_FHANDLERS_ACCESSORS(endsubmsg, upb_endfield_handler*)
UPB_FHANDLERS_ACCESSORS(startseq, upb_startfield_handler*)
UPB_FHANDLERS_ACCESSORS(endseq, upb_endfield_handler*)
UPB_FHANDLERS_ACCESSORS(submsg, struct _upb_mhandlers*)
// The startsubmsg handler needs to also pass a closure to the submsg.
struct _upb_sflow {
upb_flow_t flow;
void *closure;
};
INLINE upb_sflow_t UPB_SFLOW(upb_flow_t flow, void *closure) {
upb_sflow_t ret = {flow, closure};
return ret;
}
#define UPB_CONTINUE_WITH(c) UPB_SFLOW(UPB_CONTINUE, c)
#define UPB_SBREAK UPB_SFLOW(UPB_BREAK, NULL)
// Appends a new message to the graph of handlers and returns it. This message /* upb_mhandlers **************************************************************/
// can be obtained later at index upb_handlers_msgcount()-1. All handlers will
// be initialized to no-op handlers. // A upb_mhandlers object represents the set of handlers associated with a
upb_mhandlers *upb_handlers_newmhandlers(upb_handlers *h); // message in the graph of messages.
upb_mhandlers *upb_handlers_getmhandlers(upb_handlers *h, int index);
typedef struct _upb_mhandlers {
upb_atomic_t refcount;
upb_startmsg_handler *startmsg;
upb_endmsg_handler *endmsg;
upb_inttable fieldtab; // Maps field number -> upb_fhandlers.
uint32_t jit_startmsg_pclabel;
uint32_t jit_endofbuf_pclabel;
uint32_t jit_endofmsg_pclabel;
uint32_t jit_unknownfield_pclabel;
bool is_group;
int32_t jit_parent_field_done_pclabel;
uint32_t max_field_number;
// Currently keyed on field number. Could also try keying it
// on encoded or decoded tag, or on encoded field number.
void **tablearray;
} upb_mhandlers;
// mhandlers are created as part of a upb_handlers instance, but can be ref'd
// and unref'd to prolong the life of the handlers.
void upb_mhandlers_ref(upb_mhandlers *m);
void upb_mhandlers_unref(upb_mhandlers *m);
// Creates a new field with the given name and number. There must not be an // Creates a new field with the given name and number. There must not be an
// existing field with either this name or number or abort() will be called. // existing field with either this name or number or abort() will be called.
@ -209,17 +218,26 @@ upb_fhandlers *upb_mhandlers_newfhandlers_subm(upb_mhandlers *m, uint32_t n,
UPB_MHANDLERS_ACCESSORS(startmsg, upb_startmsg_handler*); UPB_MHANDLERS_ACCESSORS(startmsg, upb_startmsg_handler*);
UPB_MHANDLERS_ACCESSORS(endmsg, upb_endmsg_handler*); UPB_MHANDLERS_ACCESSORS(endmsg, upb_endmsg_handler*);
// upb_fhandlers accessors
#define UPB_FHANDLERS_ACCESSORS(name, type) \ /* upb_handlers ***************************************************************/
INLINE void upb_fhandlers_set ## name(upb_fhandlers *f, type v){f->name = v;} \
INLINE type upb_fhandlers_get ## name(upb_fhandlers *f) { return f->name; } struct _upb_handlers {
UPB_FHANDLERS_ACCESSORS(fval, upb_value) upb_atomic_t refcount;
UPB_FHANDLERS_ACCESSORS(value, upb_value_handler*) upb_mhandlers **msgs; // Array of msgdefs, [0]=toplevel.
UPB_FHANDLERS_ACCESSORS(startsubmsg, upb_startfield_handler*) int msgs_len, msgs_size;
UPB_FHANDLERS_ACCESSORS(endsubmsg, upb_endfield_handler*) bool should_jit;
UPB_FHANDLERS_ACCESSORS(startseq, upb_startfield_handler*) };
UPB_FHANDLERS_ACCESSORS(endseq, upb_endfield_handler*) typedef struct _upb_handlers upb_handlers;
UPB_FHANDLERS_ACCESSORS(submsg, upb_mhandlers*)
upb_handlers *upb_handlers_new();
void upb_handlers_ref(upb_handlers *h);
void upb_handlers_unref(upb_handlers *h);
// Appends a new message to the graph of handlers and returns it. This message
// can be obtained later at index upb_handlers_msgcount()-1. All handlers will
// be initialized to no-op handlers.
upb_mhandlers *upb_handlers_newmhandlers(upb_handlers *h);
upb_mhandlers *upb_handlers_getmhandlers(upb_handlers *h, int index);
// Convenience function for registering handlers for all messages and // Convenience function for registering handlers for all messages and
// fields in a msgdef and all its children. For every registered message // fields in a msgdef and all its children. For every registered message
@ -338,16 +356,15 @@ void _upb_dispatcher_unwind(upb_dispatcher *d, upb_flow_t flow);
// Dispatch functions -- call the user handler and handle errors. // Dispatch functions -- call the user handler and handle errors.
INLINE void upb_dispatch_value(upb_dispatcher *d, upb_fhandlers *f, INLINE void upb_dispatch_value(upb_dispatcher *d, upb_fhandlers *f,
upb_value val) { upb_value val) {
upb_flow_t flow = f->value(d->top->closure, f->fval, val); upb_flow_t flow = UPB_CONTINUE;
if (f->value) flow = f->value(d->top->closure, f->fval, val);
if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow); if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow);
} }
void upb_dispatch_startmsg(upb_dispatcher *d); void upb_dispatch_startmsg(upb_dispatcher *d);
void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status); void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status);
upb_dispatcher_frame *upb_dispatch_startsubmsg(upb_dispatcher *d, upb_dispatcher_frame *upb_dispatch_startsubmsg(upb_dispatcher *d, upb_fhandlers *f);
upb_fhandlers *f);
upb_dispatcher_frame *upb_dispatch_endsubmsg(upb_dispatcher *d); upb_dispatcher_frame *upb_dispatch_endsubmsg(upb_dispatcher *d);
upb_dispatcher_frame *upb_dispatch_startseq(upb_dispatcher *d, upb_dispatcher_frame *upb_dispatch_startseq(upb_dispatcher *d, upb_fhandlers *f);
upb_fhandlers *f);
upb_dispatcher_frame *upb_dispatch_endseq(upb_dispatcher *d); upb_dispatcher_frame *upb_dispatch_endseq(upb_dispatcher *d);
#ifdef __cplusplus #ifdef __cplusplus

@ -38,7 +38,7 @@ static void upb_elem_free(upb_value v, upb_fielddef *f) {
static void upb_elem_unref(upb_value v, upb_fielddef *f) { static void upb_elem_unref(upb_value v, upb_fielddef *f) {
assert(upb_elem_ismm(f)); assert(upb_elem_ismm(f));
upb_atomic_refcount_t *refcount = upb_value_getrefcount(v); upb_atomic_t *refcount = upb_value_getrefcount(v);
if (refcount && upb_atomic_unref(refcount)) if (refcount && upb_atomic_unref(refcount))
upb_elem_free(v, f); upb_elem_free(v, f);
} }
@ -53,7 +53,7 @@ static void upb_field_free(upb_value v, upb_fielddef *f) {
static void upb_field_unref(upb_value v, upb_fielddef *f) { static void upb_field_unref(upb_value v, upb_fielddef *f) {
assert(upb_field_ismm(f)); assert(upb_field_ismm(f));
upb_atomic_refcount_t *refcount = upb_value_getrefcount(v); upb_atomic_t *refcount = upb_value_getrefcount(v);
if (refcount && upb_atomic_unref(refcount)) if (refcount && upb_atomic_unref(refcount))
upb_field_free(v, f); upb_field_free(v, f);
} }
@ -63,7 +63,7 @@ static void upb_field_unref(upb_value v, upb_fielddef *f) {
upb_array *upb_array_new(void) { upb_array *upb_array_new(void) {
upb_array *arr = malloc(sizeof(*arr)); upb_array *arr = malloc(sizeof(*arr));
upb_atomic_refcount_init(&arr->refcount, 1); upb_atomic_init(&arr->refcount, 1);
arr->size = 0; arr->size = 0;
arr->len = 0; arr->len = 0;
arr->ptr = NULL; arr->ptr = NULL;
@ -134,7 +134,7 @@ upb_msg *upb_msg_new(upb_msgdef *md) {
upb_msg *msg = malloc(md->size); upb_msg *msg = malloc(md->size);
// Clear all set bits and cached pointers. // Clear all set bits and cached pointers.
memset(msg, 0, md->size); memset(msg, 0, md->size);
upb_atomic_refcount_init(&msg->refcount, 1); upb_atomic_init(&msg->refcount, 1);
return msg; return msg;
} }
@ -178,7 +178,7 @@ void upb_msg_set(upb_msg *msg, upb_fielddef *f, upb_value val) {
upb_field_unref(oldval, f); upb_field_unref(oldval, f);
// Ref the new value. // Ref the new value.
upb_atomic_refcount_t *refcount = upb_value_getrefcount(val); upb_atomic_t *refcount = upb_value_getrefcount(val);
if (refcount) upb_atomic_ref(refcount); if (refcount) upb_atomic_ref(refcount);
} }
upb_msg_sethas(msg, f); upb_msg_sethas(msg, f);
@ -194,7 +194,7 @@ upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) {
upb_msg *m = upb_msg_new(md); upb_msg *m = upb_msg_new(md);
// Copy all set bits and values, except the refcount. // Copy all set bits and values, except the refcount.
memcpy(m , upb_value_getmsg(val), md->size); memcpy(m , upb_value_getmsg(val), md->size);
upb_atomic_refcount_init(&m->refcount, 0); // The msg will take a ref. upb_atomic_init(&m->refcount, 0); // The msg will take a ref.
upb_value_setmsg(&val, m); upb_value_setmsg(&val, m);
} }
upb_msg_set(msg, f, val); upb_msg_set(msg, f, val);

@ -142,7 +142,7 @@ INLINE void upb_value_write(upb_valueptr ptr, upb_value val,
typedef uint32_t upb_arraylen_t; typedef uint32_t upb_arraylen_t;
struct _upb_array { struct _upb_array {
upb_atomic_refcount_t refcount; upb_atomic_t refcount;
// "len" and "size" are measured in elements, not bytes. // "len" and "size" are measured in elements, not bytes.
int32_t len; int32_t len;
int32_t size; int32_t size;
@ -192,7 +192,7 @@ INLINE upb_value upb_array_get(upb_array *arr, upb_fielddef *f,
// 2. you would want the msg to own a ref on its msgdef, but this would require // 2. you would want the msg to own a ref on its msgdef, but this would require
// an atomic operation for every message create or destroy! // an atomic operation for every message create or destroy!
struct _upb_msg { struct _upb_msg {
upb_atomic_refcount_t refcount; upb_atomic_t refcount;
uint8_t data[4]; // We allocate the appropriate amount per message. uint8_t data[4]; // We allocate the appropriate amount per message.
}; };

@ -35,7 +35,7 @@ upb_string *upb_string_new() {
str->size = 0; str->size = 0;
#endif #endif
str->src = NULL; str->src = NULL;
upb_atomic_refcount_init(&str->refcount, 1); upb_atomic_init(&str->refcount, 1);
return str; return str;
} }

@ -59,7 +59,7 @@ extern "C" {
// the associated functions. // the associated functions.
struct _upb_string { struct _upb_string {
// The string's refcount. // The string's refcount.
upb_atomic_refcount_t refcount; upb_atomic_t refcount;
// The pointer to our currently active data. This may be memory we own // The pointer to our currently active data. This may be memory we own
// or a pointer into memory we don't own. // or a pointer into memory we don't own.

@ -38,15 +38,15 @@ static void test_upb_jit() {
upb_string_unref(symname); upb_string_unref(symname);
ASSERT(def); ASSERT(def);
upb_handlers h; upb_handlers *h = upb_handlers_new();
upb_handlers_init(&h);
upb_handlerset hset = {NULL, NULL, &upb_test_onvalue, NULL, NULL, NULL, NULL}; upb_handlerset hset = {NULL, NULL, &upb_test_onvalue, NULL, NULL, NULL, NULL};
upb_handlers_reghandlerset(&h, upb_downcast_msgdef(def), &hset); upb_handlers_reghandlerset(h, upb_downcast_msgdef(def), &hset);
upb_decoder d; upb_decoder d;
upb_decoder_init(&d, &h); upb_decoder_init(&d, h);
upb_decoder_uninit(&d); upb_decoder_uninit(&d);
upb_symtab_unref(s); upb_symtab_unref(s);
upb_def_unref(def); upb_def_unref(def);
upb_handlers_unref(h);
} }
static void test_upb_symtab() { static void test_upb_symtab() {

Loading…
Cancel
Save