You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2010/01/04 23:09:51 UTC

svn commit: r895800 - in /lucene/lucy/trunk/core/Lucy/Object: VTable.bp VTable.c

Author: marvin
Date: Mon Jan  4 22:09:50 2010
New Revision: 895800

URL: http://svn.apache.org/viewvc?rev=895800&view=rev
Log:
Switch VTable_registry over from Hash to LockFreeRegistry.

Modified:
    lucene/lucy/trunk/core/Lucy/Object/VTable.bp
    lucene/lucy/trunk/core/Lucy/Object/VTable.c

Modified: lucene/lucy/trunk/core/Lucy/Object/VTable.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/VTable.bp?rev=895800&r1=895799&r2=895800&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/VTable.bp (original)
+++ lucene/lucy/trunk/core/Lucy/Object/VTable.bp Mon Jan  4 22:09:50 2010
@@ -18,7 +18,7 @@
     Callback         **callbacks;
     lucy_method_t[1]   methods; /* flexible array */
 
-    inert Hash *registry;
+    inert LockFreeRegistry *registry;
 
     /** Return a singleton.  If a VTable can be found in the registry based on
      * the subclass name, it will be returned.  Otherwise, a new VTable will
@@ -34,11 +34,13 @@
     /** Register a vtable, so that it can be retrieved by class name.
      *
      * TODO: Move this functionality to some kind of class loader.
+     * 
+     * @return true on success, false if the class was already registered.
      */
-    inert void
+    inert bool_t
     add_to_registry(VTable *vtable);
 
-    /** Initialize the registry hash.
+    /** Initialize the registry.
      */
     inert void
     init_registry();

Modified: lucene/lucy/trunk/core/Lucy/Object/VTable.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/VTable.c?rev=895800&r1=895799&r2=895800&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/VTable.c (original)
+++ lucene/lucy/trunk/core/Lucy/Object/VTable.c Mon Jan  4 22:09:50 2010
@@ -11,8 +11,10 @@
 #include "Lucy/Object/CharBuf.h"
 #include "Lucy/Object/Err.h"
 #include "Lucy/Object/Hash.h"
+#include "Lucy/Object/LockFreeRegistry.h"
 #include "Lucy/Object/Undefined.h"
 #include "Lucy/Object/VArray.h"
+#include "Lucy/Util/Atomic.h"
 #include "Lucy/Util/Memory.h"
 
 size_t lucy_VTable_offset_of_parent = offsetof(lucy_VTable, parent);
@@ -21,7 +23,7 @@
 static void
 S_scrunch_charbuf(CharBuf *source, CharBuf *target);
 
-Hash *VTable_registry = NULL;
+LockFreeRegistry *VTable_registry = NULL;
 
 void
 VTable_destroy(VTable *self)
@@ -90,19 +92,23 @@
 void
 VTable_init_registry()
 {
-    VTable_registry = Hash_new(0);
+    LockFreeRegistry *reg = LFReg_new(256);
+    if (Atomic_cas_ptr((void*volatile*)&VTable_registry, NULL, reg)) {
+        return;
+    }
+    else {
+        DECREF(reg);
+    }
 }
 
 VTable*
 VTable_singleton(const CharBuf *subclass_name, VTable *parent)
 {
-    VTable *singleton;
-
-    if (VTable_registry == NULL)
-        VTable_init_registry();
-
-    singleton = (VTable*)Hash_Fetch(VTable_registry, (Obj*)subclass_name);
+    if (VTable_registry == NULL) { 
+        VTable_init_registry(); 
+    }
 
+    VTable *singleton = (VTable*)LFReg_Fetch(VTable_registry, (Obj*)subclass_name);
     if (singleton == NULL) {
         VArray *novel_host_methods;
         u32_t num_novel;
@@ -155,8 +161,18 @@
         DECREF(novel_host_methods);
 
         /* Register the new class, both locally and with host. */
-        Hash_Store(VTable_registry, (Obj*)subclass_name, (Obj*)singleton);
-        VTable_register_with_host(singleton, parent);
+        if (VTable_add_to_registry(singleton)) {
+            /* Doing this after registering is racy, but hard to fix. :( */
+            VTable_register_with_host(singleton, parent);
+        }
+        else {
+            DECREF(singleton);
+            singleton = (VTable*)LFReg_Fetch(VTable_registry, (Obj*)subclass_name);
+            if (!singleton) {
+                THROW(ERR, "Failed to either insert or fetch VTable for '%o'",
+                    subclass_name);
+            }
+        }
     }
     
     return singleton;
@@ -197,21 +213,24 @@
     }
 }
 
-void
+bool_t
 VTable_add_to_registry(VTable *vtable)
 {
-    VTable *fetched;
-
-    if (VTable_registry == NULL)
+    if (VTable_registry == NULL) {
         VTable_init_registry();
-    fetched = (VTable*)Hash_Fetch(VTable_registry, (Obj*)vtable->name);
-    if (fetched) {
-        if (fetched != vtable) {
-            THROW(ERR, "Attempt to redefine a vtable for '%o'", vtable->name);
-        }
+    }
+    if (LFReg_Fetch(VTable_registry, (Obj*)vtable->name)) {
+        return false;
     }
     else {
-        Hash_Store(VTable_registry, (Obj*)vtable->name, (Obj*)vtable);
+        CharBuf *klass = CB_Clone(vtable->name);
+        if (LFReg_Register(VTable_registry, (Obj*)klass, (Obj*)vtable)) {
+            return true;
+        }
+        else {
+            DECREF(klass);
+            return false;
+        }
     }
 }
 
@@ -220,7 +239,7 @@
 {
     VTable *vtable = NULL;
     if (VTable_registry != NULL) {
-        vtable = (VTable*)Hash_Fetch(VTable_registry, (Obj*)class_name);
+        vtable = (VTable*)LFReg_Fetch(VTable_registry, (Obj*)class_name);
     }
     return vtable;
 }