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 */
/* 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);
#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 */
}
if (counter++ % 119 == 0) {
int my_index;
+ void *new_link;
{
# ifdef PCR
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) {