Use copy-on-incref Strings as immortals. Members variables of Class and Method are shared and need to be threadsafe. Copy-on-incref Strings are effectively threadsafe, so use those.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/c0b90906 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/c0b90906 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/c0b90906 Branch: refs/heads/master Commit: c0b90906746d3825e3fc9fd41d023aa727e07b13 Parents: 55b19f4 Author: Marvin Humphrey <[email protected]> Authored: Tue Feb 10 19:01:39 2015 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Tue Feb 10 19:01:39 2015 -0800 ---------------------------------------------------------------------- runtime/core/Clownfish/Class.c | 18 +++++++++++++----- runtime/core/Clownfish/Class.cfh | 1 + runtime/core/Clownfish/Method.c | 22 +++++++++++++++++++++- runtime/core/Clownfish/Method.cfh | 5 +++++ 4 files changed, 40 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c0b90906/runtime/core/Clownfish/Class.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c index 478bd6c..6e87e49 100644 --- a/runtime/core/Clownfish/Class.c +++ b/runtime/core/Clownfish/Class.c @@ -152,23 +152,30 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs) * Pass 3: * - Inititalize name and method array. * - Register class. + * + * We use a "wrapped" String for `name` because it's effectively + * threadsafe: the sole reference is owned by an immortal object and any + * INCREF spawns a copy. */ for (size_t i = 0; i < num_specs; ++i) { const ClassSpec *spec = &specs[i]; Class *klass = *spec->klass; - klass->name = Str_newf("%s", spec->name); + klass->name_internal = Str_newf("%s", spec->name); + klass->name + = Str_new_wrap_trusted_utf8(Str_Get_Ptr8(klass->name_internal), + Str_Get_Size(klass->name_internal)); klass->methods = (Method**)MALLOCATE((spec->num_novel_meths + 1) * sizeof(Method*)); // Only store novel methods for now. for (size_t i = 0; i < spec->num_novel_meths; ++i) { const NovelMethSpec *mspec = &spec->novel_meth_specs[i]; - String *name = Str_newf("%s", mspec->name); - Method *method = Method_new(name, mspec->callback_func, + StackString *name + = SSTR_WRAP_UTF8(mspec->name, strlen(mspec->name)); + Method *method = Method_new((String*)name, mspec->callback_func, *mspec->offset); klass->methods[i] = method; - DECREF(name); } klass->methods[spec->num_novel_meths] = NULL; @@ -363,11 +370,12 @@ void Class_Add_Host_Method_Alias_IMP(Class *self, const char *alias, const char *meth_name) { Method *method = S_find_method(self, meth_name); + StackString *alias_cf = SSTR_WRAP_UTF8(alias, strlen(alias)); if (!method) { fprintf(stderr, "Method %s not found\n", meth_name); abort(); } - method->host_alias = Str_newf("%s", alias); + Method_Set_Host_Alias(method, (String*)alias_cf); } void http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c0b90906/runtime/core/Clownfish/Class.cfh ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh index 566f29f..8b966b7 100644 --- a/runtime/core/Clownfish/Class.cfh +++ b/runtime/core/Clownfish/Class.cfh @@ -27,6 +27,7 @@ class Clownfish::Class inherits Clownfish::Obj { Class *parent; String *name; + String *name_internal; uint32_t flags; int32_t parcel_id; size_t obj_alloc_size; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c0b90906/runtime/core/Clownfish/Method.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Method.c b/runtime/core/Clownfish/Method.c index bf76313..931427b 100644 --- a/runtime/core/Clownfish/Method.c +++ b/runtime/core/Clownfish/Method.c @@ -31,11 +31,20 @@ Method_new(String *name, cfish_method_t callback_func, size_t offset) { Method* Method_init(Method *self, String *name, cfish_method_t callback_func, size_t offset) { - self->name = Str_Clone(name); + /* The `name` member which Method exposes via the `Get_Name` accessor uses + * a "wrapped" string because that is effectively threadsafe: an INCREF + * results in a copy and the only reference is owned by an immortal + * object. */ + self->name_internal = Str_Clone(name); + self->name + = Str_new_wrap_trusted_utf8(Str_Get_Ptr8(self->name_internal), + Str_Get_Size(self->name_internal)); + self->host_alias = NULL; self->callback_func = callback_func; self->offset = offset; self->is_excluded = false; + return self; } @@ -49,6 +58,17 @@ Method_Get_Name_IMP(Method *self) { return self->name; } +void +Method_Set_Host_Alias_IMP(Method *self, String *name) { + if (self->host_alias) { + THROW(ERR, "Can't Set_Host_Alias more than once"); + } + self->host_alias_internal = Str_Clone(name); + self->host_alias + = Str_new_wrap_trusted_utf8(Str_Get_Ptr8(self->host_alias_internal), + Str_Get_Size(self->host_alias_internal)); +} + String* Method_Get_Host_Alias_IMP(Method *self) { return self->host_alias; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c0b90906/runtime/core/Clownfish/Method.cfh ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Method.cfh b/runtime/core/Clownfish/Method.cfh index 57bc1ad..e71a549 100644 --- a/runtime/core/Clownfish/Method.cfh +++ b/runtime/core/Clownfish/Method.cfh @@ -22,7 +22,9 @@ parcel Clownfish; class Clownfish::Method inherits Clownfish::Obj { String *name; + String *name_internal; String *host_alias; + String *host_alias_internal; cfish_method_t callback_func; size_t offset; bool is_excluded; @@ -37,6 +39,9 @@ class Clownfish::Method inherits Clownfish::Obj { String* Get_Name(Method *self); + void + Set_Host_Alias(Method *self, String *name); + nullable String* Get_Host_Alias(Method *self);
