From 91a3dff9cf75635c8c2e6d14aca1140cc00a0897 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 26 Oct 2011 18:15:39 +0200 Subject: [PATCH] add GC_move_disappearing_link * 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 | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/gc.h | 13 +++++++++++++ 2 files changed, 64 insertions(+) diff --git a/finalize.c b/finalize.c index 644d9580..359f270c 100644 --- a/finalize.c +++ b/finalize.c @@ -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) diff --git a/include/gc.h b/include/gc.h index 65d4d6b0..08b43599 100644 --- a/include/gc.h +++ b/include/gc.h @@ -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 */ -- 2.40.0