You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2014/08/03 17:47:08 UTC

[1/9] git commit: Implement iterator for LockFreeRegistry

Repository: lucy-clownfish
Updated Branches:
  refs/heads/clone_class_registry [created] 859ee7e1b


Implement iterator for LockFreeRegistry


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/bfde91c3
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/bfde91c3
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/bfde91c3

Branch: refs/heads/clone_class_registry
Commit: bfde91c3a34fcfbf4965046f0ceb9955f7c17118
Parents: c1d89c3
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 16:06:05 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:38:04 2014 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/LockFreeRegistry.c   | 51 ++++++++++++++++++++++++
 runtime/core/Clownfish/LockFreeRegistry.cfh | 17 ++++++++
 2 files changed, 68 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bfde91c3/runtime/core/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/LockFreeRegistry.c b/runtime/core/Clownfish/LockFreeRegistry.c
index fab4f54..577ecb0 100644
--- a/runtime/core/Clownfish/LockFreeRegistry.c
+++ b/runtime/core/Clownfish/LockFreeRegistry.c
@@ -15,6 +15,7 @@
  */
 
 #define C_CFISH_LOCKFREEREGISTRY
+#define C_CFISH_LFREGITERATOR
 #define CFISH_USE_SHORT_NAMES
 
 #include "Clownfish/LockFreeRegistry.h"
@@ -148,4 +149,54 @@ LFReg_Destroy_IMP(LockFreeRegistry *self) {
     SUPER_DESTROY(self, LOCKFREEREGISTRY);
 }
 
+/**********************************************************************/
+
+LFRegIterator*
+LFRegIter_new(LockFreeRegistry *registry) {
+    LFRegIterator *self = (LFRegIterator*)Class_Make_Obj(LFREGITERATOR);
+    return LFRegIter_init(self, registry);
+}
+
+LFRegIterator*
+LFRegIter_init(LFRegIterator *self, LockFreeRegistry *registry) {
+    self->registry = (LockFreeRegistry*)INCREF(registry);
+    self->tick     = 0;     // Next tick.
+    self->entry    = NULL;  // Previous entry.
+    return self;
+}
+
+bool
+LFRegIter_Next_IMP(LFRegIterator *self, Obj **key, Obj**value) {
+    size_t      tick  = self->tick;
+    LFRegEntry *entry = (LFRegEntry*)self->entry;
+
+    if (entry) {
+        entry = entry->next;
+    }
+
+    LockFreeRegistry  *registry = self->registry;
+    size_t             capacity = registry->capacity;
+    LFRegEntry       **entries  = registry->entries;
+
+    while (!entry && tick < capacity) {
+        entry = entries[tick++];
+    }
+
+    self->tick  = tick;
+    self->entry = entry;
+
+    if (!entry) { return false; }
+
+    if (key)   { *key   = entry->key;   }
+    if (value) { *value = entry->value; }
+
+    return true;
+}
+
+void
+LFRegIter_Destroy_IMP(LFRegIterator *self) {
+    DECREF(self->registry);
+
+    SUPER_DESTROY(self, LFREGITERATOR);
+}
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bfde91c3/runtime/core/Clownfish/LockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/LockFreeRegistry.cfh b/runtime/core/Clownfish/LockFreeRegistry.cfh
index 2061a23..cc8be8e 100644
--- a/runtime/core/Clownfish/LockFreeRegistry.cfh
+++ b/runtime/core/Clownfish/LockFreeRegistry.cfh
@@ -45,4 +45,21 @@ class Clownfish::LockFreeRegistry nickname LFReg inherits Clownfish::Obj {
     Destroy(LockFreeRegistry *self);
 }
 
+class Clownfish::LFRegIterator nickname LFRegIter inherits Clownfish::Obj {
+    LockFreeRegistry *registry;
+    size_t            tick;
+    void             *entry;
+
+    inert incremented LFRegIterator*
+    new(LockFreeRegistry *registry);
+
+    inert LFRegIterator*
+    init(LFRegIterator *self, LockFreeRegistry *registry);
+
+    public bool
+    Next(LFRegIterator *self, Obj **key, Obj**value);
+
+    public void
+    Destroy(LFRegIterator *self);
+}
 


[7/9] git commit: Make String#Clone create a new String object

Posted by nw...@apache.org.
Make String#Clone create a new String object

In order to allow thread-safe cloning of strings, String#Clone must
create a new String object.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/a360af7d
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/a360af7d
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/a360af7d

Branch: refs/heads/clone_class_registry
Commit: a360af7d27a1d528efaf6b8655b386aeb19de307
Parents: 9eb42ea
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 14:07:22 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:38:04 2014 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/String.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a360af7d/runtime/core/Clownfish/String.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/String.c b/runtime/core/Clownfish/String.c
index c23314c..7527f48 100644
--- a/runtime/core/Clownfish/String.c
+++ b/runtime/core/Clownfish/String.c
@@ -310,7 +310,7 @@ Str_To_Utf8_IMP(String *self) {
 
 String*
 Str_Clone_IMP(String *self) {
-    return (String*)INCREF(self);
+    return Str_new_from_trusted_utf8(self->ptr, self->size);
 }
 
 String*


[4/9] git commit: Store class registry in a host-specific location

Posted by nw...@apache.org.
Store class registry in a host-specific location

For Perl, store the class registry in $Clownfish::Class::_registry. For
C, store it in a global variable.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/9eb42eaa
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/9eb42eaa
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/9eb42eaa

Branch: refs/heads/clone_class_registry
Commit: 9eb42eaa1ee7f05ab95bd89d4eea076012b34720
Parents: 165f9ff
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 14:03:58 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:38:04 2014 +0200

----------------------------------------------------------------------
 runtime/c/src/Clownfish/Class.c                 | 12 ++++
 runtime/core/Clownfish/Class.c                  | 61 ++++++++------------
 runtime/core/Clownfish/Class.cfh                | 11 ++--
 .../perl/buildlib/Clownfish/Build/Binding.pm    |  7 +--
 runtime/perl/xs/XSBind.c                        | 19 ++++++
 5 files changed, 62 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9eb42eaa/runtime/c/src/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Class.c b/runtime/c/src/Clownfish/Class.c
index 82a5892..4c626d9 100644
--- a/runtime/c/src/Clownfish/Class.c
+++ b/runtime/c/src/Clownfish/Class.c
@@ -23,9 +23,21 @@
 #include "Clownfish/Class.h"
 #include "Clownfish/String.h"
 #include "Clownfish/Err.h"
+#include "Clownfish/LockFreeRegistry.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/VArray.h"
 
+static LockFreeRegistry *class_registry = NULL;
+
+LockFreeRegistry*
+Class_get_registry() {
+    if (class_registry == NULL) {
+        class_registry = LFReg_new(256);
+    }
+
+    return class_registry;
+}
+
 Obj*
 Class_Make_Obj_IMP(Class *self) {
     Obj *obj = (Obj*)Memory_wrapped_calloc(self->obj_alloc_size, 1);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9eb42eaa/runtime/core/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c
index 0220b3a..6a3ce9d 100644
--- a/runtime/core/Clownfish/Class.c
+++ b/runtime/core/Clownfish/Class.c
@@ -50,8 +50,6 @@ S_find_method(Class *self, const char *meth_name);
 static int32_t
 S_claim_parcel_id(void);
 
-LockFreeRegistry *Class_registry = NULL;
-
 void
 Class_bootstrap(const ClassSpec *specs, size_t num_specs)
 {
@@ -140,7 +138,6 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs)
      *
      * Pass 3:
      * - Inititalize name and method array.
-     * - Register class.
      */
     for (size_t i = 0; i < num_specs; ++i) {
         const ClassSpec *spec = &specs[i];
@@ -157,8 +154,17 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs)
             VA_Push(klass->methods, (Obj*)method);
             DECREF(name);
         }
+    }
 
-        Class_add_to_registry(klass);
+    /* Pass 4:
+     * - Register class.
+     */
+    LockFreeRegistry *registry = Class_get_registry();
+    for (size_t i = 0; i < num_specs; ++i) {
+        const ClassSpec *spec = &specs[i];
+        Class *klass = *spec->klass;
+
+        LFReg_Register(registry, (Obj*)klass->name, (Obj*)klass);
     }
 }
 
@@ -235,24 +241,11 @@ Class_Get_Methods_IMP(Class *self) {
     return self->methods;
 }
 
-void
-Class_init_registry() {
-    LockFreeRegistry *reg = LFReg_new(256);
-    if (Atomic_cas_ptr((void*volatile*)&Class_registry, NULL, reg)) {
-        return;
-    }
-    else {
-        DECREF(reg);
-    }
-}
-
 Class*
 Class_singleton(String *class_name, Class *parent) {
-    if (Class_registry == NULL) {
-        Class_init_registry();
-    }
+    LockFreeRegistry *registry = Class_get_registry();
 
-    Class *singleton = (Class*)LFReg_Fetch(Class_registry, (Obj*)class_name);
+    Class *singleton = (Class*)LFReg_Fetch(registry, (Obj*)class_name);
     if (singleton == NULL) {
         VArray *fresh_host_methods;
         uint32_t num_fresh;
@@ -311,7 +304,7 @@ Class_singleton(String *class_name, Class *parent) {
         }
         else {
             DECREF(singleton);
-            singleton = (Class*)LFReg_Fetch(Class_registry, (Obj*)class_name);
+            singleton = (Class*)LFReg_Fetch(registry, (Obj*)class_name);
             if (!singleton) {
                 THROW(ERR, "Failed to either insert or fetch Class for '%o'",
                       class_name);
@@ -324,16 +317,14 @@ Class_singleton(String *class_name, Class *parent) {
 
 bool
 Class_add_to_registry(Class *klass) {
-    if (Class_registry == NULL) {
-        Class_init_registry();
-    }
-    if (LFReg_Fetch(Class_registry, (Obj*)klass->name)) {
+    LockFreeRegistry *registry = Class_get_registry();
+
+    if (LFReg_Fetch(registry, (Obj*)klass->name)) {
         return false;
     }
     else {
         String *class_name = Str_Clone(klass->name);
-        bool retval
-            = LFReg_Register(Class_registry, (Obj*)class_name, (Obj*)klass);
+        bool retval = LFReg_Register(registry, (Obj*)class_name, (Obj*)klass);
         DECREF(class_name);
         return retval;
     }
@@ -342,17 +333,15 @@ Class_add_to_registry(Class *klass) {
 bool
 Class_add_alias_to_registry(Class *klass, const char *alias_ptr,
                              size_t alias_len) {
-    if (Class_registry == NULL) {
-        Class_init_registry();
-    }
+    LockFreeRegistry *registry = Class_get_registry();
+
     StackString *alias = SSTR_WRAP_UTF8(alias_ptr, alias_len);
-    if (LFReg_Fetch(Class_registry, (Obj*)alias)) {
+    if (LFReg_Fetch(registry, (Obj*)alias)) {
         return false;
     }
     else {
         String *class_name = SStr_Clone(alias);
-        bool retval
-            = LFReg_Register(Class_registry, (Obj*)class_name, (Obj*)klass);
+        bool retval = LFReg_Register(registry, (Obj*)class_name, (Obj*)klass);
         DECREF(class_name);
         return retval;
     }
@@ -360,11 +349,9 @@ Class_add_alias_to_registry(Class *klass, const char *alias_ptr,
 
 Class*
 Class_fetch_class(String *class_name) {
-    Class *klass = NULL;
-    if (Class_registry != NULL) {
-        klass = (Class*)LFReg_Fetch(Class_registry, (Obj*)class_name);
-    }
-    return klass;
+    LockFreeRegistry *registry = Class_get_registry();
+
+    return (Class*)LFReg_Fetch(registry, (Obj*)class_name);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9eb42eaa/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index 3bab408..69dc5a4 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -34,7 +34,6 @@ class Clownfish::Class inherits Clownfish::Obj {
     VArray            *methods;
     cfish_method_t[1]  vtable; /* flexible array */
 
-    inert LockFreeRegistry *registry;
     inert size_t offset_of_parent;
 
     inert void
@@ -51,6 +50,11 @@ class Clownfish::Class inherits Clownfish::Obj {
     inert Class*
     singleton(String *class_name, Class *parent);
 
+    /* Return the global class registry, creating it if necessary.
+     */
+    inert LockFreeRegistry*
+    get_registry();
+
     /** Register a class, so that it can be retrieved by class name.
      *
      * TODO: Move this functionality to some kind of class loader.
@@ -64,11 +68,6 @@ class Clownfish::Class inherits Clownfish::Obj {
     add_alias_to_registry(Class *klass, const char *alias_ptr,
                           size_t alias_len);
 
-    /** Initialize the registry.
-     */
-    inert void
-    init_registry();
-
     /** Tell the host about the new class.
      */
     inert void

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9eb42eaa/runtime/perl/buildlib/Clownfish/Build/Binding.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build/Binding.pm b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
index ccfaeca..1b1d3c5 100644
--- a/runtime/perl/buildlib/Clownfish/Build/Binding.pm
+++ b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
@@ -572,12 +572,9 @@ sub bind_class {
 MODULE = Clownfish   PACKAGE = Clownfish::Class
 
 SV*
-_get_registry()
+_get_registry(...)
 CODE:
-    if (cfish_Class_registry == NULL) {
-        cfish_Class_init_registry();
-    }
-    RETVAL = (SV*)CFISH_Obj_To_Host((cfish_Obj*)cfish_Class_registry);
+    RETVAL = SvREFCNT_inc(get_sv("Clownfish::Class::_registry", GV_ADD));
 OUTPUT: RETVAL
 
 SV*

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9eb42eaa/runtime/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/runtime/perl/xs/XSBind.c b/runtime/perl/xs/XSBind.c
index d7c5e88..8807c86 100644
--- a/runtime/perl/xs/XSBind.c
+++ b/runtime/perl/xs/XSBind.c
@@ -675,6 +675,25 @@ CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
 
 /*************************** Clownfish::Class ******************************/
 
+cfish_LockFreeRegistry*
+cfish_Class_get_registry() {
+    SV *registry_sv = get_sv("Clownfish::Class::_registry", GV_ADD);
+    cfish_LockFreeRegistry *registry;
+
+    if (!SvOK(registry_sv)) {
+        registry = cfish_LFReg_new(256);
+        SV *new_sv = CFISH_Obj_To_Host((cfish_Obj*)registry);
+        sv_setsv(registry_sv, new_sv);
+        SvREFCNT_dec(new_sv);
+    }
+    else {
+        registry = (cfish_LockFreeRegistry*)XSBind_sv_to_cfish_obj(registry_sv, 
+                CFISH_LOCKFREEREGISTRY, NULL);
+    }
+
+    return registry;
+}
+
 cfish_Obj*
 CFISH_Class_Make_Obj_IMP(cfish_Class *self) {
     cfish_Obj *obj


[9/9] git commit: Cease sharing Class and LFReg between Perl threads

Posted by nw...@apache.org.
Cease sharing Class and LFReg between Perl threads


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/859ee7e1
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/859ee7e1
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/859ee7e1

Branch: refs/heads/clone_class_registry
Commit: 859ee7e1b43bed64c8312f6cd4f8d8f43e3ece6d
Parents: b46a446
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 17:36:24 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:46:02 2014 +0200

----------------------------------------------------------------------
 runtime/c/src/Clownfish/Class.c             |  7 ------
 runtime/c/src/Clownfish/LockFreeRegistry.c  | 32 ------------------------
 runtime/core/Clownfish/Class.cfh            |  3 ---
 runtime/core/Clownfish/LockFreeRegistry.cfh |  3 ---
 runtime/perl/xs/XSBind.c                    | 26 -------------------
 5 files changed, 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/859ee7e1/runtime/c/src/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Class.c b/runtime/c/src/Clownfish/Class.c
index 4c626d9..61aec84 100644
--- a/runtime/c/src/Clownfish/Class.c
+++ b/runtime/c/src/Clownfish/Class.c
@@ -81,10 +81,3 @@ Class_find_parent_class(String *class_name) {
     UNREACHABLE_RETURN(String*);
 }
 
-void*
-Class_To_Host_IMP(Class *self) {
-    UNUSED_VAR(self);
-    THROW(ERR, "TODO");
-    UNREACHABLE_RETURN(void*);
-}
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/859ee7e1/runtime/c/src/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/LockFreeRegistry.c b/runtime/c/src/Clownfish/LockFreeRegistry.c
deleted file mode 100644
index 396b78b..0000000
--- a/runtime/c/src/Clownfish/LockFreeRegistry.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_CFISH_LOCKFREEREGISTRY
-#define CFISH_USE_SHORT_NAMES
-
-#include "charmony.h"
-
-#include "Clownfish/LockFreeRegistry.h"
-#include "Clownfish/Err.h"
-
-void*
-LFReg_To_Host_IMP(LockFreeRegistry *self) {
-    UNUSED_VAR(self);
-    THROW(ERR, "TODO");
-    UNREACHABLE_RETURN(void*);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/859ee7e1/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index 4229ff2..968c512 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -147,9 +147,6 @@ class Clownfish::Class inherits Clownfish::Obj {
     uint32_t
     Get_RefCount(Class *self);
 
-    void*
-    To_Host(Class *self);
-
     public void
     Destroy(Class *self);
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/859ee7e1/runtime/core/Clownfish/LockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/LockFreeRegistry.cfh b/runtime/core/Clownfish/LockFreeRegistry.cfh
index cc8be8e..4defbcf 100644
--- a/runtime/core/Clownfish/LockFreeRegistry.cfh
+++ b/runtime/core/Clownfish/LockFreeRegistry.cfh
@@ -38,9 +38,6 @@ class Clownfish::LockFreeRegistry nickname LFReg inherits Clownfish::Obj {
     public incremented LockFreeRegistry*
     Clone(LockFreeRegistry *self);
 
-    void*
-    To_Host(LockFreeRegistry *self);
-
     public void
     Destroy(LockFreeRegistry *self);
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/859ee7e1/runtime/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/runtime/perl/xs/XSBind.c b/runtime/perl/xs/XSBind.c
index 8807c86..07ab582 100644
--- a/runtime/perl/xs/XSBind.c
+++ b/runtime/perl/xs/XSBind.c
@@ -775,18 +775,6 @@ cfish_Class_find_parent_class(cfish_String *class_name) {
     return parent_class;
 }
 
-void*
-CFISH_Class_To_Host_IMP(cfish_Class *self) {
-    bool first_time = self->ref.count & XSBIND_REFCOUNT_FLAG ? true : false;
-    CFISH_Class_To_Host_t to_host
-        = CFISH_SUPER_METHOD_PTR(CFISH_CLASS, CFISH_Class_To_Host);
-    SV *host_obj = (SV*)to_host(self);
-    if (first_time) {
-        SvSHARE((SV*)self->ref.host_obj);
-    }
-    return host_obj;
-}
-
 
 /*************************** Clownfish::Method ******************************/
 
@@ -964,17 +952,3 @@ cfish_Err_trap(CFISH_Err_Attempt_t routine, void *context) {
     return error;
 }
 
-/*********************** Clownfish::LockFreeRegistry ************************/
-
-void*
-CFISH_LFReg_To_Host_IMP(cfish_LockFreeRegistry *self) {
-    bool first_time = self->ref.count & XSBIND_REFCOUNT_FLAG ? true : false;
-    CFISH_LFReg_To_Host_t to_host
-        = CFISH_SUPER_METHOD_PTR(CFISH_LOCKFREEREGISTRY, CFISH_LFReg_To_Host);
-    SV *host_obj = (SV*)to_host(self);
-    if (first_time) {
-        SvSHARE((SV*)self->ref.host_obj);
-    }
-    return host_obj;
-}
-


[8/9] git commit: Clone class registry in new Perl threads

Posted by nw...@apache.org.
Clone class registry in new Perl threads

Define a CLONE method in Clownfish::Class which gets invoked when a new
Perl thread is created.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/b46a4465
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/b46a4465
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/b46a4465

Branch: refs/heads/clone_class_registry
Commit: b46a4465c8bf630eef7d2bfa4fdb5d3407d0b234
Parents: bfde91c
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 17:31:51 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:46:02 2014 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/Class.c                  | 26 ++++++++
 runtime/core/Clownfish/Class.cfh                |  3 +
 .../perl/buildlib/Clownfish/Build/Binding.pm    | 24 +++++++
 runtime/perl/lib/Clownfish.pm                   |  2 +
 runtime/perl/t/binding/600-threads.t            | 70 ++++++++++++++++++++
 5 files changed, 125 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b46a4465/runtime/core/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c
index a60aca9..8070fc1 100644
--- a/runtime/core/Clownfish/Class.c
+++ b/runtime/core/Clownfish/Class.c
@@ -355,6 +355,32 @@ Class_fetch_class(String *class_name) {
     return (Class*)LFReg_Fetch(registry, (Obj*)class_name);
 }
 
+LockFreeRegistry*
+Class_clone_registry(LockFreeRegistry *registry) {
+    LockFreeRegistry *twin  = LFReg_Clone(registry);
+    LFRegIterator    *iter  = LFRegIter_new(twin);
+    Obj              *value = NULL;
+
+    // Fix up parent pointers.
+    while (LFRegIter_Next(iter, NULL, &value)) {
+        Class  *klass       = (Class*)value;
+        Class  *orig_parent = klass->parent;
+
+        if (orig_parent) {
+            String *parent_name = Class_Get_Name(orig_parent);
+            Class  *twin_parent = (Class*)LFReg_Fetch(twin, (Obj*)parent_name);
+            if (!twin_parent) {
+                THROW(ERR, "Class '%o' not found in cloned registry",
+                      parent_name);
+            }
+            klass->parent = twin_parent;
+        }
+    }
+    DECREF(iter);
+
+    return twin;
+}
+
 void
 Class_Add_Host_Method_Alias_IMP(Class *self, const char *alias,
                              const char *meth_name) {

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b46a4465/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index 69dc5a4..4229ff2 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -79,6 +79,9 @@ class Clownfish::Class inherits Clownfish::Obj {
     inert nullable Class*
     fetch_class(String *class_name);
 
+    inert LockFreeRegistry*
+    clone_registry(LockFreeRegistry *registry);
+
     /** Given a class name, return the name of a parent class which descends
      * from Clownfish::Obj, or NULL if such a class can't be found.
      */

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b46a4465/runtime/perl/buildlib/Clownfish/Build/Binding.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build/Binding.pm b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
index 1b1d3c5..9b1d12e 100644
--- a/runtime/perl/buildlib/Clownfish/Build/Binding.pm
+++ b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
@@ -616,6 +616,30 @@ CODE:
     RETVAL = (SV*)CFISH_Class_To_Host(singleton);
 }
 OUTPUT: RETVAL
+
+void
+CLONE(class_sv, ...)
+    SV *class_sv;
+PPCODE:
+{
+    const char *class_name = SvPV_nolen(class_sv);
+
+    if (strcmp(class_name, "Clownfish::Class") == 0) {
+        SV *registry_sv = get_sv("Clownfish::Class::_registry", 0);
+
+        if (registry_sv) {
+            cfish_LockFreeRegistry *registry;
+            SV *new_sv;
+
+            registry = (cfish_LockFreeRegistry*)XSBind_sv_to_cfish_obj(
+                    registry_sv, CFISH_LOCKFREEREGISTRY, NULL);
+            registry = cfish_Class_clone_registry(registry);
+            new_sv = CFISH_Obj_To_Host((cfish_Obj*)registry);
+            sv_setsv(registry_sv, new_sv);
+            SvREFCNT_dec(new_sv);
+        }
+    }
+}
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b46a4465/runtime/perl/lib/Clownfish.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/lib/Clownfish.pm b/runtime/perl/lib/Clownfish.pm
index 5f1bdd1..4109004 100644
--- a/runtime/perl/lib/Clownfish.pm
+++ b/runtime/perl/lib/Clownfish.pm
@@ -77,6 +77,8 @@ sub error {$Clownfish::Err::error}
     our $VERSION = '0.003000';
     $VERSION = eval $VERSION;
     no warnings 'redefine';
+    # Clone LFReg manually.
+    sub CLONE_SKIP { 0; }
     sub DESTROY { }    # leak all
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b46a4465/runtime/perl/t/binding/600-threads.t
----------------------------------------------------------------------
diff --git a/runtime/perl/t/binding/600-threads.t b/runtime/perl/t/binding/600-threads.t
new file mode 100644
index 0000000..42e11d7
--- /dev/null
+++ b/runtime/perl/t/binding/600-threads.t
@@ -0,0 +1,70 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use threads;
+
+use Clownfish;
+use Test::More tests => 7;
+
+sub cf_addr {
+    my $obj = shift;
+    return 0 + $$obj;
+}
+
+my $obj           = Clownfish::String->new('A string.');
+my $registry_addr = cf_addr(Clownfish::Class->_get_registry);
+my $class         = Clownfish::Class->fetch_class('Clownfish::Hash');
+my $class_addr    = cf_addr($class);
+my $parent        = $class->get_parent;
+my $parent_addr   = cf_addr($parent);
+
+my ($thread) = threads->create(sub {
+    my $thr_registry = Clownfish::Class->_get_registry;
+    my $thr_class    = Clownfish::Class->fetch_class('Clownfish::Hash');
+    my $thr_parent   = $thr_class->get_parent;
+    my $thr_other_parent
+        = Clownfish::Class->fetch_class($thr_parent->get_name);
+    return (
+        defined($$obj),
+        cf_addr($thr_registry),
+        cf_addr($thr_class),
+        cf_addr($thr_parent),
+        cf_addr($thr_other_parent),
+    );
+});
+my (
+    $thr_obj_defined,
+    $thr_registry_addr,
+    $thr_class_addr,
+    $thr_parent_addr,
+    $thr_other_parent_addr,
+) = $thread->join;
+
+ok( !$thr_obj_defined, "Object is undefined in other thread" );
+
+my $other_registry_addr = cf_addr(Clownfish::Class->_get_registry);
+my $other_class         = Clownfish::Class->fetch_class('Clownfish::Hash');
+my $other_class_addr    = cf_addr($class);
+
+is( $other_registry_addr, $registry_addr, "Same registry in same thread" );
+is( $other_class_addr, $class_addr, "Same class in same thread" );
+isnt( $thr_registry_addr, $registry_addr, "Cloned registry in other thread" );
+isnt( $thr_class_addr, $class_addr, "Cloned class in other thread" );
+isnt( $thr_parent_addr, $parent_addr, "Cloned parent class in other thread" );
+is( $thr_parent_addr, $thr_other_parent_addr, "Parent classes fixed up" );
+


[3/9] git commit: Special case String hash keys

Posted by nw...@apache.org.
Special case String hash keys

For immutable strings, it's enough to incref the hash key.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/a081f6b5
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/a081f6b5
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/a081f6b5

Branch: refs/heads/clone_class_registry
Commit: a081f6b590653b3e3fc3ca5cba1d4cc356c426a9
Parents: a360af7
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 14:11:46 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:38:04 2014 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/Hash.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a081f6b5/runtime/core/Clownfish/Hash.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Hash.c b/runtime/core/Clownfish/Hash.c
index 987631c..70181c0 100644
--- a/runtime/core/Clownfish/Hash.c
+++ b/runtime/core/Clownfish/Hash.c
@@ -16,6 +16,7 @@
 
 #define C_CFISH_HASH
 #define C_CFISH_HASHTOMBSTONE
+#define C_CFISH_OBJ
 #define CFISH_USE_SHORT_NAMES
 
 #include <string.h>
@@ -166,7 +167,13 @@ Obj*
 Hash_Make_Key_IMP(Hash *self, Obj *key, int32_t hash_sum) {
     UNUSED_VAR(self);
     UNUSED_VAR(hash_sum);
-    return Obj_Clone(key);
+    if (key->klass == STRING || key->klass == STACKSTRING) {
+        // Strings are immutable.
+        return INCREF(key);
+    }
+    else {
+        return Obj_Clone(key);
+    }
 }
 
 Obj*


[6/9] git commit: Make sure to clone a Class's methods

Posted by nw...@apache.org.
Make sure to clone a Class's methods


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/fd30d706
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/fd30d706
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/fd30d706

Branch: refs/heads/clone_class_registry
Commit: fd30d706d5e06019c36c744d3023954d73614f75
Parents: 8598709
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 14:32:07 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:38:04 2014 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/Class.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/fd30d706/runtime/core/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c
index 6a3ce9d..a60aca9 100644
--- a/runtime/core/Clownfish/Class.c
+++ b/runtime/core/Clownfish/Class.c
@@ -180,7 +180,8 @@ Class_Clone_IMP(Class *self) {
 
     memcpy(twin, self, self->class_alloc_size);
     Class_Init_Obj(self->klass, twin); // Set refcount.
-    twin->name = Str_Clone(self->name);
+    twin->name    = Str_Clone(self->name);
+    twin->methods = VA_Clone(self->methods);
 
     return twin;
 }


[2/9] git commit: Implement Method#Clone

Posted by nw...@apache.org.
Implement Method#Clone


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/8598709b
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/8598709b
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/8598709b

Branch: refs/heads/clone_class_registry
Commit: 8598709b6b163f795df1f2b0a4a5de4a7f6b3335
Parents: a081f6b
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 14:19:35 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:38:04 2014 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/Method.c   | 15 ++++++++++++++-
 runtime/core/Clownfish/Method.cfh |  3 +++
 2 files changed, 17 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8598709b/runtime/core/Clownfish/Method.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Method.c b/runtime/core/Clownfish/Method.c
index d7a7327..52ecd0d 100644
--- a/runtime/core/Clownfish/Method.c
+++ b/runtime/core/Clownfish/Method.c
@@ -31,7 +31,7 @@ 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);
+    self->name          = (String*)INCREF(name);
     self->host_alias    = NULL;
     self->callback_func = callback_func;
     self->offset        = offset;
@@ -39,6 +39,19 @@ Method_init(Method *self, String *name, cfish_method_t callback_func,
     return self;
 }
 
+Method*
+Method_Clone_IMP(Method *self) {
+    String *name  = Str_Clone(self->name);
+    Method *twin = Method_new(name, self->callback_func, self->offset);
+    DECREF(name);
+
+    if (self->host_alias) {
+        twin->host_alias = Str_Clone(self->host_alias);
+    }
+
+    return twin;
+}
+
 void
 Method_Destroy_IMP(Method *self) {
     THROW(ERR, "Insane attempt to destroy Method '%o'", self->name);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8598709b/runtime/core/Clownfish/Method.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Method.cfh b/runtime/core/Clownfish/Method.cfh
index feab12f..1294a7c 100644
--- a/runtime/core/Clownfish/Method.cfh
+++ b/runtime/core/Clownfish/Method.cfh
@@ -46,6 +46,9 @@ class Clownfish::Method inherits Clownfish::Obj {
     incremented String*
     Host_Name(Method *self);
 
+    public incremented Method*
+    Clone(Method *self);
+
     incremented Obj*
     Inc_RefCount(Method *self);
 


[5/9] git commit: Implement LFReg#Clone

Posted by nw...@apache.org.
Implement LFReg#Clone


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/c1d89c3a
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/c1d89c3a
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/c1d89c3a

Branch: refs/heads/clone_class_registry
Commit: c1d89c3a3ab7c152da1165ae190ead024aafb9d5
Parents: fd30d70
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun Aug 3 14:53:13 2014 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 3 17:38:04 2014 +0200

----------------------------------------------------------------------
 runtime/core/Clownfish/LockFreeRegistry.c       | 23 ++++++++++++++++++++
 runtime/core/Clownfish/LockFreeRegistry.cfh     |  9 +++++---
 .../core/Clownfish/Test/TestLockFreeRegistry.c  |  9 +++++++-
 3 files changed, 37 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c1d89c3a/runtime/core/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/LockFreeRegistry.c b/runtime/core/Clownfish/LockFreeRegistry.c
index c95a791..fab4f54 100644
--- a/runtime/core/Clownfish/LockFreeRegistry.c
+++ b/runtime/core/Clownfish/LockFreeRegistry.c
@@ -106,6 +106,29 @@ LFReg_Fetch_IMP(LockFreeRegistry *self, Obj *key) {
     return NULL;
 }
 
+LockFreeRegistry*
+LFReg_Clone_IMP(LockFreeRegistry *self) {
+    size_t             capacity = self->capacity;
+    LFRegEntry       **entries  = (LFRegEntry**)self->entries;
+    LockFreeRegistry  *twin     = LFReg_new(capacity);
+
+    for (size_t i = 0; i < capacity; ++i) {
+        LFRegEntry *entry = entries[i];
+
+        while (entry) {
+            Obj *key   = Obj_Clone(entry->key);
+            Obj *value = Obj_Clone(entry->value);
+            LFReg_Register(twin, key, value);
+            DECREF(key);
+            DECREF(value);
+
+            entry = entry->next;
+        }
+    }
+
+    return twin;
+}
+
 void
 LFReg_Destroy_IMP(LockFreeRegistry *self) {
     LFRegEntry **entries = (LFRegEntry**)self->entries;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c1d89c3a/runtime/core/Clownfish/LockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/LockFreeRegistry.cfh b/runtime/core/Clownfish/LockFreeRegistry.cfh
index bb41fbd..2061a23 100644
--- a/runtime/core/Clownfish/LockFreeRegistry.cfh
+++ b/runtime/core/Clownfish/LockFreeRegistry.cfh
@@ -29,17 +29,20 @@ class Clownfish::LockFreeRegistry nickname LFReg inherits Clownfish::Obj {
     inert LockFreeRegistry*
     init(LockFreeRegistry *self, size_t capacity);
 
-    public void
-    Destroy(LockFreeRegistry *self);
-
     bool
     Register(LockFreeRegistry *self, Obj *key, Obj *value);
 
     nullable Obj*
     Fetch(LockFreeRegistry *self, Obj *key);
 
+    public incremented LockFreeRegistry*
+    Clone(LockFreeRegistry *self);
+
     void*
     To_Host(LockFreeRegistry *self);
+
+    public void
+    Destroy(LockFreeRegistry *self);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c1d89c3a/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestLockFreeRegistry.c b/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
index 46d725e..fb69065 100644
--- a/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
+++ b/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
@@ -66,6 +66,13 @@ test_all(TestBatchRunner *runner) {
     TEST_TRUE(runner, LFReg_Fetch(registry, (Obj*)baz) == NULL,
               "Fetch() non-existent key returns NULL");
 
+    LockFreeRegistry *twin = LFReg_Clone(registry);
+    Obj *twin_entry = LFReg_Fetch(twin, (Obj*)foo);
+    TEST_TRUE(runner, twin_entry != NULL, "Fetch() from clone");
+    TEST_TRUE(runner, Obj_Equals(twin_entry, (Obj*)foo),
+              "Fetch() from clone returns equal entry");
+    TEST_TRUE(runner, twin_entry != (Obj*)foo, "Clone() performs deep clone");
+
     DECREF(foo_dupe);
     DECREF(baz);
     DECREF(bar);
@@ -75,7 +82,7 @@ test_all(TestBatchRunner *runner) {
 
 void
 TestLFReg_Run_IMP(TestLockFreeRegistry *self, TestBatchRunner *runner) {
-    TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 9);
     test_all(runner);
 }