summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2014-04-17 15:29:13 +0200
committerAndy Wingo <wingo@pobox.com>2014-04-26 14:46:45 +0200
commitfa1a30726dc28c58cb01594ae6df27e80d4c2f00 (patch)
treeab8f16a7d36b110a0cc8cc04b8384c4f816ea31f
parente0da53b4fe4abee2cdcd97fe46eeefcaab1da631 (diff)
downloadguile-fa1a30726dc28c58cb01594ae6df27e80d4c2f00.tar.gz
Add interface to disable automatic finalization
* libguile/finalizers.h: * libguile/finalizers.c (run_finalizers_async_thunk): Call the new scm_run_finalizers helper. (scm_set_automatic_finalization_enabled, scm_run_finalizers): New functions. (scm_init_finalizers): 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.
-rw-r--r--doc/ref/api-smobs.texi32
-rw-r--r--doc/ref/libguile-smobs.texi23
-rw-r--r--libguile/finalizers.c47
-rw-r--r--libguile/finalizers.h5
4 files changed, 101 insertions, 6 deletions
diff --git a/doc/ref/api-smobs.texi b/doc/ref/api-smobs.texi
index 345bf7cbd..cfabd3988 100644
--- a/doc/ref/api-smobs.texi
+++ b/doc/ref/api-smobs.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2013
+@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2013, 2014
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
@@ -60,6 +60,36 @@ memory is automatically reclaimed by the garbage collector when it is no
longer needed (@pxref{Memory Blocks, @code{scm_gc_malloc}}).
@end deftypefn
+Smob free functions must be thread-safe. @xref{Garbage Collecting
+Smobs}, for a discussion on finalizers and concurrency. If you are
+embedding Guile in an application that is not thread-safe, and you
+define smob types that need finalization, you might want to disable
+automatic finalization, and arrange to call
+@code{scm_manually_run_finalizers ()} yourself.
+
+@deftypefn {C Function} int scm_set_automatic_finalization_enabled (int enabled_p)
+Enable or disable automatic finalization. By default, Guile arranges to
+invoke object finalizers automatically, in a separate thread if
+possible. Passing a zero value for @var{enabled_p} will disable
+automatic finalization for Guile as a whole. If you disable automatic
+finalization, you will have to call @code{scm_run_finalizers ()}
+periodically.
+
+Unlike most other Guile functions, you can call
+@code{scm_set_automatic_finalization_enabled} before Guile has been
+initialized.
+
+Return the previous status of automatic finalization.
+@end deftypefn
+
+@deftypefn {C Function} int scm_run_finalizers (void)
+Invoke any pending finalizers. Returns the number of finalizers that
+were invoked. This function should be called when automatic
+finalization is disabled, though it may be called if it is enabled as
+well.
+@end deftypefn
+
+
@cindex precise marking
@deftypefn {C Function} void scm_set_smob_mark (scm_t_bits tc, SCM (*mark) (SCM obj))
diff --git a/doc/ref/libguile-smobs.texi b/doc/ref/libguile-smobs.texi
index 572bcf316..f12ab1303 100644
--- a/doc/ref/libguile-smobs.texi
+++ b/doc/ref/libguile-smobs.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011, 2013
+@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011, 2013, 2014
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
@@ -385,6 +385,27 @@ During the sweep phase, the garbage collector will clear the mark bits
on all live objects. The code which implements a smob need not do this
itself.
+@cindex finalizer
+@cindex finalization
+
+Note that the free function can be called in any context. In
+particular, if your Guile is built with support for threads, the
+finalizer may be called from any thread that is running Guile. In Guile
+2.0, finalizers are invoked via ``asyncs'', which interleaves them with
+running Scheme code; @pxref{System asyncs}. In Guile 2.2 there will be
+a dedicated finalization thread, to ensure that the finalization doesn't
+run within the critical section of any other thread known to Guile.
+
+In either case, finalizers (free functions) run concurrently with the
+main program, and so they need to be async-safe and thread-safe. If for
+some reason this is impossible, perhaps because you are embedding Guile
+in some application that is not itself thread-safe, you have a few
+options. One is to use guardians instead of free functions, and arrange
+to pump the guardians for finalizable objects. @xref{Guardians}, for
+more information. The other option is to disable automatic finalization
+entirely, and arrange to call @code{scm_run_finalizers ()} at
+appropriate points. @xref{Smobs}, for more on these interfaces.
+
There is no way for smob code to be notified when collection is
complete.
diff --git a/libguile/finalizers.c b/libguile/finalizers.c
index a179479f5..6abc70091 100644
--- a/libguile/finalizers.c
+++ b/libguile/finalizers.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2012 Free Software Foundation, Inc.
+/* Copyright (C) 2012, 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
@@ -31,6 +31,8 @@
+static int automatic_finalization_p = 1;
+
static size_t finalization_count;
@@ -130,7 +132,7 @@ static SCM finalizer_async_cell;
static SCM
run_finalizers_async_thunk (void)
{
- finalization_count += GC_invoke_finalizers ();
+ scm_run_finalizers ();
return SCM_UNSPECIFIED;
}
@@ -169,6 +171,43 @@ GC_set_finalizer_notifier (void (*notifier) (void))
}
#endif
+
+
+
+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;
+ }
+
+ GC_set_finalizer_notifier (enabled_p ? queue_finalizer_async : 0);
+
+ 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
scm_init_finalizers (void)
{
@@ -178,5 +217,7 @@ 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);
}
diff --git a/libguile/finalizers.h b/libguile/finalizers.h
index bad96e145..12ccbb689 100644
--- a/libguile/finalizers.h
+++ b/libguile/finalizers.h
@@ -1,7 +1,7 @@
#ifndef SCM_FINALIZERS_H
#define SCM_FINALIZERS_H
-/* Copyright (C) 2012 Free Software Foundation, Inc.
+/* Copyright (C) 2012, 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
@@ -34,6 +34,9 @@ SCM_INTERNAL void scm_i_add_finalizer (void *obj, scm_t_finalizer_proc,
SCM_INTERNAL void scm_i_add_resuscitator (void *obj, scm_t_finalizer_proc,
void *data);
+SCM_API int scm_set_automatic_finalization_enabled (int enabled_p);
+SCM_API int scm_run_finalizers (void);
+
SCM_INTERNAL void scm_init_finalizers (void);
#endif /* SCM_FINALIZERS_H */