mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-09 13:30:26 +02:00
(Remembering During Operations): New section.
This commit is contained in:
parent
94270e8175
commit
7e88be2ee8
1 changed files with 77 additions and 2 deletions
|
@ -46,7 +46,7 @@
|
|||
@c essay @sp 10
|
||||
@c essay @comment The title is printed in a large font.
|
||||
@c essay @title Data Representation in Guile
|
||||
@c essay @subtitle $Id: data-rep.texi,v 1.10 2003-05-03 22:21:59 kryde Exp $
|
||||
@c essay @subtitle $Id: data-rep.texi,v 1.11 2003-06-11 23:07:53 kryde Exp $
|
||||
@c essay @subtitle For use with Guile @value{VERSION}
|
||||
@c essay @author Jim Blandy
|
||||
@c essay @author Free Software Foundation
|
||||
|
@ -1393,6 +1393,7 @@ datatypes described here.)
|
|||
* Garbage Collecting Smobs::
|
||||
* A Common Mistake In Allocating Smobs::
|
||||
* Garbage Collecting Simple Smobs::
|
||||
* Remembering During Operations::
|
||||
* A Complete Example::
|
||||
@end menu
|
||||
|
||||
|
@ -1859,7 +1860,7 @@ traverse @code{image}, so any objects @code{image} points to will be
|
|||
preserved.
|
||||
|
||||
|
||||
@node Garbage Collecting Simple Smobs, A Complete Example, A Common Mistake In Allocating Smobs, Defining New Types (Smobs)
|
||||
@node Garbage Collecting Simple Smobs
|
||||
@subsection Garbage Collecting Simple Smobs
|
||||
|
||||
It is often useful to define very simple smob types --- smobs which have
|
||||
|
@ -1893,6 +1894,80 @@ This function should not be needed anymore, because simply passing
|
|||
@end deftypefun
|
||||
|
||||
|
||||
@node Remembering During Operations
|
||||
@subsection Remembering During Operations
|
||||
@cindex Remembering
|
||||
|
||||
It's important that a smob is visible to the garbage collector
|
||||
whenever its contents are being accessed. Otherwise it could be freed
|
||||
while code is still using it.
|
||||
|
||||
@c NOTE: The varargs scm_remember_upto_here is deliberately not
|
||||
@c documented, because we don't think it can be implemented as a nice
|
||||
@c inline compiler directive or asm block. New _3, _4 or whatever
|
||||
@c forms could certainly be added though, if needed.
|
||||
|
||||
@deftypefn {C Macro} void scm_remember_upto_here_1 (SCM obj)
|
||||
@deftypefnx {C Macro} void scm_remember_upto_here_2 (SCM obj1, SCM obj2)
|
||||
Create a reference to the given object or objects, so they're certain
|
||||
to be present on the stack or in a register and hence will not be
|
||||
freed by the garbage collector before this point.
|
||||
@end deftypefn
|
||||
|
||||
For example, consider a procedure to convert image data to a list of
|
||||
pixel values.
|
||||
|
||||
@example
|
||||
SCM
|
||||
image_to_list (SCM image_smob)
|
||||
@{
|
||||
struct image *image;
|
||||
SCM lst;
|
||||
int i;
|
||||
SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
|
||||
image_smob, SCM_ARG1, "image->list");
|
||||
|
||||
image = (struct image *) SCM_SMOB_DATA (image_smob);
|
||||
lst = SCM_EOL;
|
||||
for (i = image->width * image->height - 1; i >= 0; i--)
|
||||
lst = scm_cons (SCM_MAKINUM (image->pixels[i]), lst);
|
||||
|
||||
scm_remember_upto_here_1 (image_smob);
|
||||
return lst;
|
||||
@}
|
||||
@end example
|
||||
|
||||
In the loop, only the @code{image} pointer is used and the C compiler
|
||||
has no reason to keep the @code{image_smob} value anywhere. If
|
||||
@code{scm_cons} results in a garbage collect, @code{image_smob} might
|
||||
not be on the stack or anywhere else and could be freed, leaving the
|
||||
loop accessing freed data. The use of @code{scm_remember_upto_here_1}
|
||||
prevents this, by creating a reference to @code{image_smob} after all
|
||||
data accesses.
|
||||
|
||||
There's no need to do the same for @code{lst}, since that's the return
|
||||
value and the compiler will certainly keep it in a register or
|
||||
somewhere throughout the routine.
|
||||
|
||||
The @code{clear_image} example previously shown (@pxref{Type
|
||||
checking}) did not use @code{scm_remember_upto_here_1}. This is
|
||||
because it didn't do anything that could result in a garbage collect.
|
||||
|
||||
It's only in quite rare circumstances that a missing
|
||||
@code{scm_remember_upto_here_1} will bite, but when it happens the
|
||||
consequences are serious. Fortunately the rule is simple: whenever
|
||||
allocating memory or doing something that might, ensure the @code{SCM}
|
||||
of a smob is referenced past all accesses to its insides. Do this by
|
||||
adding an @code{scm_remember_upto_here_1} if there are no other
|
||||
references.
|
||||
|
||||
In a multi-threaded program, the rule is the same. As far as a given
|
||||
thread is concerned, a garbage collect still only occurs within a
|
||||
memory allocation function, not at an arbitrary time. (Guile waits
|
||||
for all threads to reach a memory function, and holds them there while
|
||||
the collector runs.)
|
||||
|
||||
|
||||
@node A Complete Example
|
||||
@subsection A Complete Example
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue