Refactor GC_move_disappearing_link() code;
authorIvan Maidanski <ivmai@mail.ru>
Mon, 7 Nov 2011 07:30:44 +0000 (11:30 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Mon, 7 Nov 2011 07:30:44 +0000 (11:30 +0400)
make GC_move_disappearing_link(link,link) return GC_SUCCESS

* finalize.c (GC_move_disappearing_link): Rename "from", "to"
arguments to "link" and "new_link", respectively.
* include/gc.h (GC_move_disappearing_link): Likewise.
* finalize.c (GC_move_disappearing_link): Rename "to_curr_dl",
"from_index", "to_index" local variables to "new_dl", "curr_index",
"new_index", respectively.
* finalize.c (GC_move_disappearing_link): Add curr_hidden_link,
new_hidden_link local variables to evaluate GC_HIDE_POINTER(link) and
GC_HIDE_POINTER(new_link) only once.
* finalize.c (GC_move_disappearing_link): Reformat code.
* finalize.c (GC_move_disappearing_link): Do not ABORT in case of
unaligned "link", return GC_NOT_FOUND instead (similar to
GC_unregister_disappearing_link behavior).
* finalize.c (GC_move_disappearing_link): If new_link is equal to
link then return GC_SUCCESS instead of GC_DUPLICATE.
* include/gc.h (GC_move_disappearing_link, GC_NOT_FOUND): Refine and
update documentation comment.
* tests/test.c (mktree): Add "new_link" local variable; add
GC_move_disappearing_link invocations; apply
GC_unregister_disappearing_link to "new_link".

finalize.c
include/gc.h
tests/test.c

index 359f270..b8f59c7 100644 (file)
@@ -243,55 +243,64 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
     return(0);
 }
 
-GC_API int GC_CALL GC_move_disappearing_link(void * * from, void * * to)
+GC_API int GC_CALL GC_move_disappearing_link(void **link, void **new_link)
 {
-    struct disappearing_link *curr_dl, *prev_dl;
-    size_t from_index, to_index;
+    struct disappearing_link *curr_dl, *prev_dl, *new_dl;
+    size_t curr_index, new_index;
+    word curr_hidden_link;
+    word new_hidden_link;
     DCL_LOCK_STATE;
 
-    if (((word)from & (ALIGNMENT-1)) || from == NULL)
-        ABORT("Bad from arg to GC_move_disappearing_link");
-    if (((word)to & (ALIGNMENT-1)) || to == NULL)
-        ABORT("Bad to arg to GC_move_disappearing_link");
+    if (((word)new_link & (ALIGNMENT-1)) != 0 || new_link == NULL)
+      ABORT("Bad new_link arg to GC_move_disappearing_link");
+    if (((word)link & (ALIGNMENT-1)) != 0)
+      return GC_NOT_FOUND; /* Nothing to do. */
 
     LOCK();
-    from_index = HASH2(from, log_dl_table_size);
-    prev_dl = 0; curr_dl = dl_head[from_index];
-    while (curr_dl != 0) {
-        if (curr_dl -> dl_hidden_link == GC_HIDE_POINTER(from)) {
-            /* Found the from link. */
-
-            to_index = HASH2(to, log_dl_table_size);
-            {
-                struct disappearing_link *to_curr_dl;
-                for (to_curr_dl = dl_head[to_index]; to_curr_dl != 0;
-                     to_curr_dl = dl_next(to_curr_dl)) {
-                    if (to_curr_dl -> dl_hidden_link == GC_HIDE_POINTER(to)) {
-                        /* Target already registered; bail.  */
-                        UNLOCK();
-                        return GC_DUPLICATE;
-                    }
-                }
-            }
+    /* Find current link.       */
+    curr_index = HASH2(link, log_dl_table_size);
+    curr_hidden_link = GC_HIDE_POINTER(link);
+    prev_dl = 0;
+    for (curr_dl = dl_head[curr_index]; curr_dl != 0;
+         curr_dl = dl_next(curr_dl)) {
+      if (curr_dl -> dl_hidden_link == curr_hidden_link)
+        break;
+      prev_dl = curr_dl;
+    }
 
-            /* Remove from old, add to new, update link.  */
-            if (prev_dl == 0) {
-                dl_head[from_index] = dl_next(curr_dl);
-            } else {
-                dl_set_next(prev_dl, dl_next(curr_dl));
-            }
-            curr_dl -> dl_hidden_link = GC_HIDE_POINTER (to);
-            dl_set_next(curr_dl, dl_head[to_index]);
-            dl_head[to_index] = curr_dl;
+    if (curr_dl == 0) {
+      UNLOCK();
+      return GC_NOT_FOUND;
+    }
 
-            UNLOCK();
-            return GC_SUCCESS;
-        }
-        prev_dl = curr_dl;
-        curr_dl = dl_next(curr_dl);
+    if (link == new_link) {
+      UNLOCK();
+      return GC_SUCCESS; /* Nothing to do.      */
+    }
+
+    /* link found; now check new_link not present.      */
+    new_index = HASH2(new_link, log_dl_table_size);
+    new_hidden_link = GC_HIDE_POINTER(new_link);
+    for (new_dl = dl_head[new_index]; new_dl != 0;
+         new_dl = dl_next(new_dl)) {
+      if (new_dl -> dl_hidden_link == new_hidden_link) {
+        /* Target already registered; bail.     */
+        UNLOCK();
+        return GC_DUPLICATE;
+      }
+    }
+
+    /* Remove from old, add to new, update link.        */
+    if (prev_dl == 0) {
+      dl_head[curr_index] = dl_next(curr_dl);
+    } else {
+      dl_set_next(prev_dl, dl_next(curr_dl));
     }
+    curr_dl -> dl_hidden_link = new_hidden_link;
+    dl_set_next(curr_dl, dl_head[new_index]);
+    dl_head[new_index] = curr_dl;
     UNLOCK();
-    return GC_NOT_FOUND;
+    return GC_SUCCESS;
 }
 
 /* Possible finalization_marker procedures.  Note that mark stack       */
index 08b4359..65133b7 100644 (file)
@@ -950,16 +950,19 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void ** /* link */);
         /* routines.  Returns 0 if link was not actually        */
         /* registered (otherwise returns 1).                    */
 
-GC_API int GC_CALL GC_move_disappearing_link (void ** /* from */,
-                                              void ** /* to */);
+GC_API int GC_CALL GC_move_disappearing_link(void ** /* link */,
+                                             void ** /* new_link */);
         /* Moves a link previously registered via               */
-        /* GC_general_register_disappearing_link or             */
-        /* GC_register_disappearing_link.  Does not change the  */
-        /* target object of the weak reference.                 */
-        /* Returns GC_SUCCESS on success, GC_DUPLICATE if there */
-        /* was already a disappearing link at the new location, */
-        /* or GC_NOT_FOUND if no link was registered at the     */
-        /* original location.                                   */
+        /* GC_general_register_disappearing_link (or            */
+        /* GC_register_disappearing_link).  Does not change the */
+        /* target object of the weak reference.  Does not       */
+        /* change (*new_link) content.  May be called with      */
+        /* new_link equal to link (to check whether link has    */
+        /* been registered).  Returns GC_SUCCESS on success,    */
+        /* GC_DUPLICATE if there is already another             */
+        /* disappearing link at the new location (never         */
+        /* returned if new_link is equal to link), GC_NOT_FOUND */
+        /* if no link is registered at the original location.   */
 
 /* Returns !=0 if GC_invoke_finalizers has something to do.     */
 GC_API int GC_CALL GC_should_invoke_finalizers(void);
@@ -1062,8 +1065,8 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,
 #define GC_NO_THREADS 2         /* No thread support in GC.             */
         /* GC_NO_THREADS is not returned by any GC function anymore.    */
 #define GC_UNIMPLEMENTED 3 /* Not yet implemented on this platform.     */
-#define GC_NOT_FOUND 4          /* Used by GC_move_disappearing_link to */
-                                /* indicate that the link wasn't found. */
+#define GC_NOT_FOUND 4          /* Requested link not found (returned   */
+                                /* by GC_move_disappearing_link).       */
 
 #if defined(GC_DARWIN_THREADS) || defined(GC_WIN32_THREADS)
   /* Use implicit thread registration and processing (via Win32 DllMain */
index 6fd8898..92fd767 100644 (file)
@@ -736,6 +736,7 @@ tn * mktree(int n)
     }
     if (counter++ % 119 == 0) {
         int my_index;
+        void *new_link;
 
         {
 #         ifdef PCR
@@ -773,12 +774,26 @@ tn * mktree(int n)
                 GC_printf("GC_general_register_disappearing_link failed\n");
                 FAIL;
         }
-        if (GC_unregister_disappearing_link(
-                (void * *)
-                   (&(live_indicators[my_index]))) == 0) {
+        if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])),
+                   (void **)(&(live_indicators[my_index]))) != GC_SUCCESS) {
+                GC_printf("GC_move_disappearing_link(link,link) failed\n");
+                FAIL;
+        }
+        new_link = (void *)live_indicators[my_index];
+        if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])),
+                                      &new_link) != GC_SUCCESS) {
+                GC_printf("GC_move_disappearing_link(new_link) failed\n");
+                FAIL;
+        }
+        if (GC_unregister_disappearing_link(&new_link) == 0) {
                 GC_printf("GC_unregister_disappearing_link failed\n");
                 FAIL;
         }
+        if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])),
+                                      &new_link) != GC_NOT_FOUND) {
+                GC_printf("GC_move_disappearing_link(new_link) failed 2\n");
+                FAIL;
+        }
         if (GC_GENERAL_REGISTER_DISAPPEARING_LINK(
                 (void * *)(&(live_indicators[my_index])),
                 (void *)result) != 0) {