1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

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.
This commit is contained in:
Andy Wingo 2014-04-17 15:29:13 +02:00
parent e0da53b4fe
commit fa1a30726d
4 changed files with 101 additions and 6 deletions

View file

@ -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))

View file

@ -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.

View file

@ -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);
if (automatic_finalization_p)
GC_set_finalizer_notifier (queue_finalizer_async);
}

View file

@ -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 */