Skip to content

Commit

Permalink
Make all handlers objects refcounted.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Joshua Haberman committed May 22, 2011
1 parent 2ccebb7 commit a503b88
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 208 deletions.
8 changes: 4 additions & 4 deletions benchmarks/parsestream.upb_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ static upb_string *input_str;
static upb_msgdef *def;
static upb_decoder decoder;
static upb_stringsrc stringsrc;
upb_handlers handlers;

static upb_sflow_t startsubmsg(void *_m, upb_value fval) {
(void)_m;
Expand Down Expand Up @@ -61,11 +60,12 @@ static bool initialize()
return false;
}

upb_handlers_init(&handlers);
upb_handlers *handlers = upb_handlers_new();
// Cause all messages to be read, but do nothing when they are.
upb_handlerset hset = {NULL, NULL, value, startsubmsg, NULL, NULL, NULL};
upb_handlers_reghandlerset(&handlers, def, &hset);
upb_decoder_init(&decoder, &handlers);
upb_handlers_reghandlerset(handlers, def, &hset);
upb_decoder_init(&decoder, handlers);
upb_handlers_unref(handlers);
upb_stringsrc_init(&stringsrc);
return true;
}
Expand Down
8 changes: 4 additions & 4 deletions benchmarks/parsetostruct.upb_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ static upb_msgdef *def;
static upb_msg *msg;
static upb_stringsrc strsrc;
static upb_decoder d;
static upb_handlers h;

static bool initialize()
{
Expand Down Expand Up @@ -53,9 +52,10 @@ static bool initialize()
msg = upb_msg_new(def);

upb_stringsrc_init(&strsrc);
upb_handlers_init(&h);
upb_msg_reghandlers(&h, def);
upb_decoder_init(&d, &h);
upb_handlers *handlers = upb_handlers_new();
upb_msg_reghandlers(handlers, def);
upb_decoder_init(&d, handlers);
upb_handlers_unref(handlers);

if (!BYREF) {
// Pretend the input string is stack-allocated, which will force its data
Expand Down
4 changes: 2 additions & 2 deletions src/upb.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ typedef struct {
upb_bytesrc *bytesrc;
upb_msg *msg;
upb_array *arr;
upb_atomic_refcount_t *refcount;
upb_atomic_t *refcount;
upb_fielddef *fielddef;
void *_void;
} val;
Expand Down Expand Up @@ -204,7 +204,7 @@ UPB_VALUE_ACCESSORS(fielddef, fielddef, upb_fielddef*, UPB_VALUETYPE_FIELDDEF);

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) ||
val.type == UPB_TYPE(STRING) ||
val.type == UPB_VALUETYPE_ARRAY);
Expand Down
52 changes: 18 additions & 34 deletions src/upb_atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,19 @@ extern "C" {

typedef struct {
int v;
} upb_atomic_refcount_t;
} upb_atomic_t;

INLINE void upb_atomic_refcount_init(upb_atomic_refcount_t *a, int val) {
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;
}
#define UPB_ATOMIC_INIT(x) {x}

INLINE int upb_atomic_read(upb_atomic_refcount_t *a) {
return a->v;
}

INLINE bool upb_atomic_add(upb_atomic_refcount_t *a, int val) {
INLINE void upb_atomic_init(upb_atomic_t *a, int val) { a->v = val; }
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_t *a, int val) {
a->v += val;
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

/* Atomic refcount ************************************************************/
Expand All @@ -82,26 +66,26 @@ INLINE int upb_atomic_fetch_and_add(upb_atomic_refcount_t *a, int val) {

typedef struct {
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;
__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;
}

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;
}

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;
}

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);
}

Expand All @@ -112,17 +96,17 @@ INLINE bool upb_atomic_read(upb_atomic_refcount_t *a) {

typedef struct {
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);
}

INLINE bool upb_atomic_ref(upb_atomic_refcount_t *a) {
INLINE bool upb_atomic_ref(upb_atomic_t *a) {
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;
}

Expand All @@ -131,7 +115,7 @@ INLINE bool upb_atomic_unref(upb_atomic_refcount_t *a) {
Implement them or compile with UPB_THREAD_UNSAFE.
#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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/upb_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,10 @@ void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc, void *closure) {
}

void upb_decoder_uninit(upb_decoder *d) {
upb_dispatcher_uninit(&d->dispatcher);
upb_string_unref(d->bufstr);
upb_string_unref(d->tmp);
#ifdef UPB_USE_JIT_X64
if (d->dispatcher.handlers->should_jit) upb_decoder_freejit(d);
#endif
upb_dispatcher_uninit(&d->dispatcher);
}
12 changes: 6 additions & 6 deletions src/upb_decoder_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
|=>f->jit_pclabel_notypecheck:
if (f->repeated) {
if (f->startseq != upb_startfield_nop) {
if (f->startseq) {
| mov ARG1_64, CLOSURE
| loadfval f
| callp f->startseq
Expand Down Expand Up @@ -394,7 +394,7 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
// Call callbacks.
if (upb_issubmsgtype(f->type)) {
// Call startsubmsg handler (if any).
if (f->startsubmsg != upb_startfield_nop) {
if (f->startsubmsg) {
// upb_sflow_t startsubmsg(void *closure, upb_value fval)
| mov r12d, ARG3_32
| callp f->startsubmsg
Expand Down Expand Up @@ -423,7 +423,7 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
| popframe

// Call endsubmsg handler (if any).
if (f->endsubmsg != upb_endfield_nop) {
if (f->endsubmsg) {
// upb_flow_t endsubmsg(void *closure, upb_value fval);
| mov ARG1_64, CLOSURE
| loadfval f
Expand All @@ -441,7 +441,7 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
| checktag tag
| je <1
| popframe
if (f->endseq != upb_endfield_nop) {
if (f->endseq) {
| mov ARG1_64, CLOSURE
| loadfval f
| callp f->endseq
Expand All @@ -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) {
|=>m->jit_startmsg_pclabel:
// Call startmsg handler (if any):
if (m->startmsg != upb_startmsg_nop) {
if (m->startmsg) {
// upb_flow_t startmsg(void *closure);
| mov ARG1_64, FRAME->closure
| callp m->startmsg
Expand Down Expand Up @@ -520,7 +520,7 @@ static void upb_decoder_jit_msg(upb_decoder *d, upb_mhandlers *m) {

|=>m->jit_endofmsg_pclabel:
// 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) {
| mov ARG1_64, FRAME->closure
| lea ARG2_64, DECODER->dispatcher.status
Expand Down
10 changes: 5 additions & 5 deletions src/upb_def.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->search_depth = 0;
def->fqname = NULL;
upb_atomic_refcount_init(&def->refcount, 1);
upb_atomic_init(&def->refcount, 1);
}

static void upb_def_uninit(upb_def *def) {
Expand Down Expand Up @@ -868,7 +868,7 @@ static upb_flow_t upb_msgdef_startmsg(void *_b) {
upb_defbuilder *b = _b;
upb_msgdef *m = malloc(sizeof(*m));
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_strtable_init(&m->ntof, 4, sizeof(upb_ntof_ent));
m->default_message = NULL;
Expand Down Expand Up @@ -898,7 +898,7 @@ static void upb_msgdef_endmsg(void *_b, upb_status *status) {

// Assign offsets in the msg.
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;
for (int i = 0; i < n; i++) {
Expand Down Expand Up @@ -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.
size_t offset = upb_align_up(m->size, align);
// 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;
max_align = UPB_MAX(max_align, align);
}
Expand Down Expand Up @@ -1242,7 +1242,7 @@ static bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs,
upb_symtab *upb_symtab_new()
{
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_strtable_init(&s->symtab, 16, sizeof(upb_symtab_ent));
s->fds_msgdef = NULL;
Expand Down
8 changes: 4 additions & 4 deletions src/upb_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ typedef int8_t upb_deftype_t;

typedef struct {
upb_string *fqname; // Fully qualified.
upb_atomic_refcount_t refcount;
upb_atomic_t refcount;
upb_deftype_t type;

// The is_cyclic flag could go in upb_msgdef instead of here, because only
Expand Down Expand Up @@ -110,7 +110,7 @@ struct _upb_fielddef {

// For the case of an enum or a submessage, points to the def for that type.
upb_def *def;
upb_atomic_refcount_t refcount;
upb_atomic_t refcount;
};

// A variety of tests about the type of a field.
Expand Down Expand Up @@ -159,7 +159,7 @@ INLINE bool upb_elem_ismm(upb_fielddef *f) {
// Structure that describes a single .proto message type.
typedef struct _upb_msgdef {
upb_def base;
upb_atomic_refcount_t cycle_refcount;
upb_atomic_t cycle_refcount;
uint32_t size;
uint32_t set_flags_bytes;

Expand Down Expand Up @@ -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
// in descriptor.proto) via the upb_stream interface.
struct _upb_symtab {
upb_atomic_refcount_t refcount;
upb_atomic_t refcount;
upb_rwlock_t lock; // Protects all members except the refcount.
upb_strtable symtab; // The symbol table.
upb_msgdef *fds_msgdef; // Msgdef for google.protobuf.FileDescriptorSet.
Expand Down
24 changes: 12 additions & 12 deletions src/upb_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ void upb_strtomsg(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str);

upb_handlers h;
upb_handlers_init(&h);
upb_msg_reghandlers(&h, md);
upb_handlers *h = upb_handlers_new();
upb_msg_reghandlers(h, md);

upb_decoder d;
upb_decoder_init(&d, &h);
upb_decoder_init(&d, h);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), msg);
upb_handlers_unref(h);

upb_decoder_decode(&d, status);

Expand All @@ -38,33 +38,33 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_stringsink_reset(&strsink, str);

upb_textprinter *p = upb_textprinter_new();
upb_handlers h;
upb_handlers_init(&h);
upb_textprinter_reghandlers(&h, md);
upb_handlers *h = upb_handlers_new();
upb_textprinter_reghandlers(h, md);
upb_textprinter_reset(p, upb_stringsink_bytesink(&strsink), single_line);

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
// capable of returning an error.
assert(upb_ok(&status));
upb_status_uninit(&status);

upb_stringsink_uninit(&strsink);
upb_textprinter_free(p);
upb_handlers_unref(h);
}

void upb_parsedesc(upb_symtab *symtab, upb_string *str, upb_status *status) {
upb_stringsrc strsrc;
upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str);

upb_handlers h;
upb_handlers_init(&h);
upb_defbuilder_reghandlers(&h);
upb_handlers *h = upb_handlers_new();
upb_defbuilder_reghandlers(h);

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_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), b);

Expand Down
Loading

0 comments on commit a503b88

Please sign in to comment.