diff options
-rw-r--r-- | libgc/finalize.c | 13 | ||||
-rw-r--r-- | libgc/include/gc.h | 4 | ||||
-rw-r--r-- | mono/metadata/boehm-gc.c | 32 |
3 files changed, 49 insertions, 0 deletions
diff --git a/libgc/finalize.c b/libgc/finalize.c index 91f6970180c..5626e872137 100644 --- a/libgc/finalize.c +++ b/libgc/finalize.c @@ -366,6 +366,15 @@ GC_process_togglerefs (void) GC_toggleref_array_size = w; } +/* Finalizer proc support */ +static void (*GC_object_finalized_proc) (GC_PTR obj); + +void +GC_set_finalizer_notify_proc (void (*proc) (GC_PTR obj)) +{ + GC_object_finalized_proc = proc; +} + static void push_and_mark_object (GC_PTR p) { @@ -877,6 +886,10 @@ void GC_finalize() fo_set_next(prev_fo, next_fo); } GC_fo_entries--; + + if (GC_object_finalized_proc) + GC_object_finalized_proc (real_ptr); + /* Add to list of objects awaiting finalization. */ fo_set_next(curr_fo, GC_finalize_now); GC_finalize_now = curr_fo; diff --git a/libgc/include/gc.h b/libgc/include/gc.h index a3eb3c2dc06..4693a3d9a54 100644 --- a/libgc/include/gc.h +++ b/libgc/include/gc.h @@ -778,6 +778,10 @@ GC_API int GC_unregister_long_link GC_PROTO((GC_PTR * /* link */)); GC_API void GC_toggleref_register_callback GC_PROTO((int (*proccess_toggleref) (GC_PTR obj))); GC_API void GC_toggleref_add (GC_PTR object, int strong_ref); +/* finalizer callback support */ +GC_API void GC_set_finalizer_notify_proc GC_PROTO((void (*object_finalized) (GC_PTR obj))); + + /* Returns !=0 if GC_invoke_finalizers has something to do. */ GC_API int GC_should_invoke_finalizers GC_PROTO((void)); diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 82bc43bace4..a27a004f7c6 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -59,6 +59,9 @@ boehm_thread_unregister (MonoThreadInfo *p); static void register_test_toggleref_callback (void); +#define BOEHM_GC_BIT_FINALIZER_AWARE 1 +static MonoGCFinalizerCallbacks fin_callbacks; + static void mono_gc_warning (char *msg, GC_word arg) { @@ -1259,6 +1262,10 @@ BOOL APIENTRY mono_gc_dllmain (HMODULE module_handle, DWORD reason, LPVOID reser guint mono_gc_get_vtable_bits (MonoClass *class) { + if (fin_callbacks.is_class_finalization_aware) { + if (fin_callbacks.is_class_finalization_aware (class)) + return BOEHM_GC_BIT_FINALIZER_AWARE; + } return 0; } @@ -1338,4 +1345,29 @@ register_test_toggleref_callback (void) mono_gc_toggleref_register_callback (test_toggleref_callback); } +static gboolean +is_finalization_aware (MonoObject *obj) +{ + MonoVTable *vt = obj->vtable; + return (vt->gc_bits & BOEHM_GC_BIT_FINALIZER_AWARE) == BOEHM_GC_BIT_FINALIZER_AWARE; +} + +static void +fin_notifier (MonoObject *obj) +{ + if (is_finalization_aware (obj)) + fin_callbacks.object_queued_for_finalization (obj); +} + +void +mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks) +{ + if (callbacks->version != MONO_GC_FINALIZER_EXTENSION_VERSION) + g_error ("Invalid finalizer callback version. Expected %d but got %d\n", MONO_GC_FINALIZER_EXTENSION_VERSION, callbacks->version); + + fin_callbacks = *callbacks; + + GC_set_finalizer_notify_proc ((void (*) (GC_PTR))fin_notifier); +} + #endif /* no Boehm GC */ |