diff options
author | Andy Wingo <wingo@pobox.com> | 2014-04-17 15:29:13 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2014-04-17 15:29:13 +0200 |
commit | d6651f690315df2ad14c2c043ffb6c949c28884e (patch) | |
tree | 4719dd303351aa47ce517fd3229c920a3a2f2001 /libguile/finalizers.c | |
parent | f5765cc25eb56ab2e11a25066c0d8e2b9d292324 (diff) | |
download | guile-d6651f690315df2ad14c2c043ffb6c949c28884e.tar.gz |
Add interface to disable automatic finalization
* libguile/finalizers.h:
* libguile/finalizers.c (run_finalizers_async_thunk)
(finalization_thread_proc): Call the new scm_run_finalizers helper.
(scm_i_finalizer_pre_fork): Only spawn the thread if automatic
finalization is enabled.
(scm_set_automatic_finalization_enabled, scm_run_finalizers): New
functions.
(scm_init_finalizers, scm_init_finalizer_thread): Only set a finalizer
notifier if automatic finalization is enabled.
* doc/ref/libguile-smobs.texi (Garbage Collecting Smobs): Add discussion
of concurrency.
* doc/ref/api-smobs.texi (Smobs): Document new functions.
Diffstat (limited to 'libguile/finalizers.c')
-rw-r--r-- | libguile/finalizers.c | 81 |
1 files changed, 72 insertions, 9 deletions
diff --git a/libguile/finalizers.c b/libguile/finalizers.c index eaea1392f..b37dbde6b 100644 --- a/libguile/finalizers.c +++ b/libguile/finalizers.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2012, 2013 Free Software Foundation, Inc. +/* Copyright (C) 2012, 2013, 2014 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -38,6 +38,8 @@ +static int automatic_finalization_p = 1; + static size_t finalization_count; @@ -137,7 +139,7 @@ static SCM finalizer_async_cell; static SCM run_finalizers_async_thunk (void) { - finalization_count += GC_invoke_finalizers (); + scm_run_finalizers (); return SCM_UNSPECIFIED; } @@ -226,7 +228,7 @@ finalization_thread_proc (void *unused) switch (data.byte) { case 0: - finalization_count += GC_invoke_finalizers (); + scm_run_finalizers (); break; case 1: return NULL; @@ -291,8 +293,11 @@ void scm_i_finalizer_pre_fork (void) { #if SCM_USE_PTHREAD_THREADS - stop_finalization_thread (); - GC_set_finalizer_notifier (spawn_finalizer_thread); + if (automatic_finalization_p) + { + stop_finalization_thread (); + GC_set_finalizer_notifier (spawn_finalizer_thread); + } #endif } @@ -355,6 +360,59 @@ scm_i_register_weak_gc_callback (SCM obj, void (*callback) (SCM)) } +int +scm_set_automatic_finalization_enabled (int enabled_p) +{ + int was_enabled_p = automatic_finalization_p; + + if (enabled_p == was_enabled_p) + return was_enabled_p; + + if (!scm_initialized_p) + { + automatic_finalization_p = enabled_p; + return was_enabled_p; + } + + if (enabled_p) + { +#if SCM_USE_PTHREAD_THREADS + if (pipe2 (finalization_pipe, O_CLOEXEC) != 0) + scm_syserror (NULL); + GC_set_finalizer_notifier (spawn_finalizer_thread); +#else + GC_set_finalizer_notifier (queue_finalizer_async); +#endif + } + else + { + GC_set_finalizer_notifier (0); + +#if SCM_USE_PTHREAD_THREADS + stop_finalization_thread (); + close (finalization_pipe[0]); + close (finalization_pipe[1]); + finalization_pipe[0] = -1; + finalization_pipe[1] = -1; +#endif + } + + automatic_finalization_p = enabled_p; + + return was_enabled_p; +} + +int +scm_run_finalizers (void) +{ + int finalized = GC_invoke_finalizers (); + + finalization_count += finalized; + + return finalized; +} + + void @@ -366,15 +424,20 @@ scm_init_finalizers (void) scm_cons (scm_c_make_gsubr ("%run-finalizers", 0, 0, 0, run_finalizers_async_thunk), SCM_BOOL_F); - GC_set_finalizer_notifier (queue_finalizer_async); + + if (automatic_finalization_p) + GC_set_finalizer_notifier (queue_finalizer_async); } void scm_init_finalizer_thread (void) { #if SCM_USE_PTHREAD_THREADS - if (pipe2 (finalization_pipe, O_CLOEXEC) != 0) - scm_syserror (NULL); - GC_set_finalizer_notifier (spawn_finalizer_thread); + if (automatic_finalization_p) + { + if (pipe2 (finalization_pipe, O_CLOEXEC) != 0) + scm_syserror (NULL); + GC_set_finalizer_notifier (spawn_finalizer_thread); + } #endif } |