From 7fa19a3f958c9a2ed7387cb373f0aa7bba707922 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 15 Aug 2009 20:53:39 -0700 Subject: Finish upb_context thread-safety. --- src/upb_context.c | 44 ++++++++++++++++++++++++++++++++------------ src/upb_context.h | 2 +- tests/tests.c | 6 +++--- tools/upbc.c | 13 ++++++------- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/upb_context.c b/src/upb_context.c index fbe3f34..0001a98 100644 --- a/src/upb_context.c +++ b/src/upb_context.c @@ -23,8 +23,9 @@ bool addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs, google_protobuf_FileDescriptorProto *fd, bool sort, struct upb_context *context); -bool upb_context_init(struct upb_context *c) +struct upb_context *upb_context_new() { + struct upb_context *c = malloc(sizeof(*c)); upb_atomic_refcount_init(&c->refcount, 1); upb_rwlock_init(&c->lock); upb_strtable_init(&c->symtab, 16, sizeof(struct upb_symtab_entry)); @@ -34,7 +35,7 @@ bool upb_context_init(struct upb_context *c) upb_file_descriptor_set->file->elements[0]; /* We know there is only 1. */ if(!addfd(&c->psymtab, &c->symtab, fd, false, c)) { assert(false); - return false; /* Indicates that upb is buggy or corrupt. */ + return NULL; /* Indicates that upb is buggy or corrupt. */ } struct upb_string name = UPB_STRLIT("google.protobuf.FileDescriptorSet"); struct upb_symtab_entry *e = upb_strtable_lookup(&c->psymtab, &name); @@ -43,7 +44,7 @@ bool upb_context_init(struct upb_context *c) c->fds_size = 16; c->fds_len = 0; c->fds = malloc(sizeof(*c->fds)); - return true; + return c; } static void free_symtab(struct upb_strtable *t) @@ -68,6 +69,7 @@ static void free_context(struct upb_context *c) upb_msg_free((struct upb_msg*)c->fds[i]); free_symtab(&c->psymtab); free(c->fds); + free(c); } void upb_context_unref(struct upb_context *c) @@ -83,7 +85,10 @@ void upb_context_unref(struct upb_context *c) struct upb_symtab_entry *upb_context_lookup(struct upb_context *c, struct upb_string *symbol) { - return upb_strtable_lookup(&c->symtab, symbol); + upb_rwlock_rdlock(&c->lock); + struct upb_symtab_entry *e = upb_strtable_lookup(&c->symtab, symbol); + upb_rwlock_unlock(&c->lock); + return e; } /* Given a symbol and the base symbol inside which it is defined, find the @@ -137,7 +142,10 @@ union upb_symbol_ref resolve2(struct upb_strtable *t1, struct upb_strtable *t2, struct upb_symtab_entry *upb_context_resolve(struct upb_context *c, struct upb_string *base, struct upb_string *symbol) { - return resolve(&c->symtab, base, symbol); + upb_rwlock_rdlock(&c->lock); + struct upb_symtab_entry *e = resolve(&c->symtab, base, symbol); + upb_rwlock_unlock(&c->lock); + return e; } /* Joins strings together, for example: @@ -280,17 +288,25 @@ bool upb_context_addfds(struct upb_context *c, * the descriptor is valid. */ struct upb_strtable tmp; upb_strtable_init(&tmp, 0, sizeof(struct upb_symtab_entry)); + upb_rwlock_rdlock(&c->lock); for(uint32_t i = 0; i < fds->file->len; i++) { if(!addfd(&tmp, &c->symtab, fds->file->elements[i], true, c)) { printf("Not added successfully!\n"); free_symtab(&tmp); + upb_rwlock_unlock(&c->lock); return false; } } + upb_rwlock_unlock(&c->lock); + /* Everything was successfully added, copy from the tmp symtable. */ struct upb_symtab_entry *e; - for(e = upb_strtable_begin(&tmp); e; e = upb_strtable_next(&tmp, &e->e)) - upb_strtable_insert(&c->symtab, &e->e); + { + upb_rwlock_wrlock(&c->lock); + for(e = upb_strtable_begin(&tmp); e; e = upb_strtable_next(&tmp, &e->e)) + upb_strtable_insert(&c->symtab, &e->e); + upb_rwlock_unlock(&c->lock); + } upb_strtable_free(&tmp); } return true; @@ -302,11 +318,15 @@ bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) { if(!fds) return false; if(!upb_context_addfds(c, fds)) return false; - /* We own fds now, need to keep a ref so we can free it later. */ - if(c->fds_size == c->fds_len) { - c->fds_size *= 2; - c->fds = realloc(c->fds, c->fds_size); + { + /* We own fds now, need to keep a ref so we can free it later. */ + upb_rwlock_wrlock(&c->lock); + if(c->fds_size == c->fds_len) { + c->fds_size *= 2; + c->fds = realloc(c->fds, c->fds_size); + } + c->fds[c->fds_len++] = fds; + upb_rwlock_unlock(&c->lock); } - c->fds[c->fds_len++] = fds; return true; } diff --git a/src/upb_context.h b/src/upb_context.h index a04a875..504b1b6 100644 --- a/src/upb_context.h +++ b/src/upb_context.h @@ -53,7 +53,7 @@ struct upb_context { /* Initializes a upb_context. Contexts are not freed explicitly, but unref'd * when the caller is done with them. */ -bool upb_context_init(struct upb_context *c); +struct upb_context *upb_context_new(); INLINE void upb_context_ref(struct upb_context *c) { upb_atomic_ref(&c->refcount); } diff --git a/tests/tests.c b/tests/tests.c index 5df933c..e625f8a 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -222,9 +222,9 @@ static void test_get_f_uint32_t() } static void test_upb_context() { - struct upb_context c; - ASSERT(upb_context_init(&c)); - upb_context_unref(&c); + struct upb_context *c = upb_context_new(); + ASSERT(c); + upb_context_unref(c); } int main() diff --git a/tools/upbc.c b/tools/upbc.c index b3036a0..2185ee3 100644 --- a/tools/upbc.c +++ b/tools/upbc.c @@ -646,13 +646,12 @@ int main(int argc, char *argv[]) error("Couldn't read input file."); /* Parse input file. */ - struct upb_context c; - upb_context_init(&c); - struct upb_msg *fds_msg = upb_msg_parsenew(c.fds_msg, descriptor); + struct upb_context *c = upb_context_new(); + struct upb_msg *fds_msg = upb_msg_parsenew(c->fds_msg, descriptor); google_protobuf_FileDescriptorSet *fds = (void*)fds_msg; if(!fds) error("Failed to parse input file descriptor."); - if(!upb_context_addfds(&c, fds)) + if(!upb_context_addfds(c, fds)) error("Failed to resolve symbols in descriptor.\n"); /* We need to sort the fields of all the descriptors. They will already be @@ -676,17 +675,17 @@ int main(int argc, char *argv[]) if(!h_file) error("Failed to open .h output file"); int symcount; - struct upb_symtab_entry **entries = strtable_to_array(&c.symtab, &symcount); + struct upb_symtab_entry **entries = strtable_to_array(&c->symtab, &symcount); write_h(entries, symcount, h_filename, cident, h_file); free(entries); if(cident) { FILE *c_file = fopen(c_filename, "w"); if(!c_file) error("Failed to open .h output file"); - write_message_c(fds, c.fds_msg, cident, h_filename, argc, argv, input_file, c_file); + write_message_c(fds, c->fds_msg, cident, h_filename, argc, argv, input_file, c_file); fclose(c_file); } upb_msg_free(fds_msg); - upb_context_unref(&c); + upb_context_unref(c); upb_strfree(descriptor); fclose(h_file); -- cgit v1.2.3