]> granicus.if.org Git - gc/commitdiff
add GC_move_disappearing_link
authorAndy Wingo <wingo@pobox.com>
Wed, 26 Oct 2011 16:15:39 +0000 (18:15 +0200)
committerIvan Maidanski <ivmai@mail.ru>
Thu, 3 Nov 2011 07:55:14 +0000 (11:55 +0400)
* finalize.c (GC_move_disappearing_link): New function, moves a
  disappearing link.

* include/gc.h: Add declaration, and new return code GC_NOT_FOUND.

finalize.c
include/gc.h

index 644d9580f7cf2f9d8fca1dbad9b257d2bb035ad9..359f270c251063bbce526cf008050d764fa1bc07 100644 (file)
@@ -243,6 +243,57 @@ 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)
+{
+    struct disappearing_link *curr_dl, *prev_dl;
+    size_t from_index, to_index;
+    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");
+
+    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;
+                    }
+                }
+            }
+
+            /* 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;
+
+            UNLOCK();
+            return GC_SUCCESS;
+        }
+        prev_dl = curr_dl;
+        curr_dl = dl_next(curr_dl);
+    }
+    UNLOCK();
+    return GC_NOT_FOUND;
+}
+
 /* Possible finalization_marker procedures.  Note that mark stack       */
 /* overflow is handled by the caller, and is not a disaster.            */
 STATIC void GC_normal_finalize_mark_proc(ptr_t p)
index 65d4d6b08b7d1dcd8aa60a851319e858fe604e88..08b43599e790eb242eab9d1880ec8cfdcf89eba8 100644 (file)
@@ -950,6 +950,17 @@ 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 */);
+        /* 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.                                   */
+
 /* Returns !=0 if GC_invoke_finalizers has something to do.     */
 GC_API int GC_CALL GC_should_invoke_finalizers(void);
 
@@ -1051,6 +1062,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. */
 
 #if defined(GC_DARWIN_THREADS) || defined(GC_WIN32_THREADS)
   /* Use implicit thread registration and processing (via Win32 DllMain */