summaryrefslogtreecommitdiff
path: root/libguile/finalizers.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2014-04-17 15:29:13 +0200
committerAndy Wingo <wingo@pobox.com>2014-04-17 15:29:13 +0200
commitd6651f690315df2ad14c2c043ffb6c949c28884e (patch)
tree4719dd303351aa47ce517fd3229c920a3a2f2001 /libguile/finalizers.c
parentf5765cc25eb56ab2e11a25066c0d8e2b9d292324 (diff)
downloadguile-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.c81
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
}