@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004
+@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.
@menu
* Describing a New Type::
-* Creating Instances::
+* Creating Smob Instances::
* Type checking::
* Garbage Collecting Smobs::
-* Garbage Collecting Simple Smobs::
* Remembering During Operations::
* Double Smobs::
* The Complete Example::
@node Describing a New Type
@subsection Describing a New Type
-To define a new type, the programmer must write four functions to
+To define a new type, the programmer must write two functions to
manage instances of the type:
@table @code
-@item mark
-Guile will apply this function to each instance of the new type it
-encounters during garbage collection. This function is responsible for
-telling the collector about any other @code{SCM} values that the object
-has stored. The default smob mark function does nothing.
-@xref{Garbage Collecting Smobs}, for more details.
-
-@item free
-Guile will apply this function to each instance of the new type that is
-to be deallocated. The function should release all resources held by
-the object. This is analogous to the Java finalization method-- it is
-invoked at an unspecified time (when garbage collection occurs) after
-the object is dead. The default free function frees the smob data (if
-the size of the struct passed to @code{scm_make_smob_type} is non-zero)
-using @code{scm_gc_free}. @xref{Garbage Collecting Smobs}, for more
-details.
-
@item print
Guile will apply this function to each instance of the new type to print
the value, as for @code{display} or @code{write}. The default print
function prints @code{#<NAME ADDRESS>} where @code{NAME} is the first
-argument passed to @code{scm_make_smob_type}. For more information on
-printing, see @ref{Port Data}.
+argument passed to @code{scm_make_smob_type}.
@item equalp
If Scheme code asks the @code{equal?} function to compare two instances
@end table
+When the only resource associated with a smob is memory managed by the
+garbage collector---i.e., memory allocated with the @code{scm_gc_malloc}
+functions---this is sufficient. However, when a smob is associated with
+other kinds of resources, it may be necessary to define one of the
+following functions, or both:
+
+@table @code
+@item mark
+Guile will apply this function to each instance of the new type it
+encounters during garbage collection. This function is responsible for
+telling the collector about any other @code{SCM} values that the object
+has stored, and that are in memory regions not already scanned by the
+garbage collector. @xref{Garbage Collecting Smobs}, for more details.
+
+@item free
+Guile will apply this function to each instance of the new type that is
+to be deallocated. The function should release all resources held by
+the object. This is analogous to the Java finalization method---it is
+invoked at an unspecified time (when garbage collection occurs) after
+the object is dead. @xref{Garbage Collecting Smobs}, for more details.
+
+This function operates while the heap is in an inconsistent state and
+must therefore be careful. @xref{Smobs}, for details about what this
+function is allowed to do.
+@end table
+
To actually register the new smob type, call @code{scm_make_smob_type}.
It returns a value of type @code{scm_t_bits} which identifies the new
smob type.
-The four special functions descrtibed above are registered by calling
+The four special functions described above are registered by calling
one of @code{scm_set_smob_mark}, @code{scm_set_smob_free},
@code{scm_set_smob_print}, or @code{scm_set_smob_equalp}, as
appropriate. Each function is intended to be used at most once per
There can only be at most 256 different smob types in the system.
Instead of registering a huge number of smob types (for example, one
for each relevant C struct in your application), it is sometimes
-better to register just one and implement a second alyer of type
+better to register just one and implement a second layer of type
dispatching on top of it. This second layer might use the 16 extra
-bits for as an extended type, for example.
+bits to extend its type, for example.
Here is how one might declare and register a new type representing
eight-bit gray-scale images:
@end example
-@node Creating Instances
-@subsection Creating Instances
+@node Creating Smob Instances
+@subsection Creating Smob Instances
-Normally, smobs can have one @emph{immediate} words of data. This word
+Normally, smobs can have one @emph{immediate} word of data. This word
stores either a pointer to an additional memory block that holds the
real data, or it might hold the data itself when it fits. The word is
-of type @code{scm_t_bits} and is large enough for a @code{SCM} value or
-a pointer to @code{void}.
+large enough for a @code{SCM} value, a pointer to @code{void}, or an
+integer that fits into a @code{size_t} or @code{ssize_t}.
You can also create smobs that have two or three immediate words, and
when these words suffice to store all data, it is more efficient to use
these super-sized smobs instead of using a normal smob plus a memory
block. @xref{Double Smobs}, for their discussion.
+Guile provides functions for managing memory which are often helpful
+when implementing smobs. @xref{Memory Blocks}.
+
To retrieve the immediate word of a smob, you use the macro
@code{SCM_SMOB_DATA}. It can be set with @code{SCM_SET_SMOB_DATA}.
The 16 extra bits can be accessed with @code{SCM_SMOB_FLAGS} and
@code{SCM_SET_SMOB_FLAGS}.
-Guile provides functions for managing memory which are often helpful
-when implementing smobs. @xref{Memory Blocks}.
+The two macros @code{SCM_SMOB_DATA} and @code{SCM_SET_SMOB_DATA} treat
+the immediate word as if it were of type @code{scm_t_bits}, which is
+an unsigned integer type large enough to hold a pointer to
+@code{void}. Thus you can use these macros to store arbitrary
+pointers in the smob word.
+
+When you want to store a @code{SCM} value directly in the immediate
+word of a smob, you should use the macros @code{SCM_SMOB_OBJECT} and
+@code{SCM_SET_SMOB_OBJECT} to access it.
Creating a smob instance can be tricky when it consists of multiple
-steps that allocate resources and might fail. It is recommended that
-you go about creating a smob in the following way:
-
-@itemize
-@item
-Allocate the memory block for holding the data with
-@code{scm_gc_malloc}.
-@item
-Initialize it to a valid state without calling any functions that might
-cause a non-local exits. For example, initialize pointers to NULL.
-Also, do not store @code{SCM} values in it that must be protected.
-Initialize these fields with @code{SCM_BOOL_F}.
-
-A valid state is one that can be safely acted upon by the @emph{mark}
-and @emph{free} functions of your smob type.
-@item
-Create the smob using @code{SCM_NEWSMOB}, passing it the initialized
-memory block. (This step will always succeed.)
-@item
-Complete the initialization of the memory block by, for example,
-allocating additional resources and making it point to them.
-@end itemize
-
-This precedure ensures that the smob is in a valid state as soon as it
-exists, that all resources that are allocated for the smob are properly
-associated with it so that they can be properly freed, and that no
-@code{SCM} values that need to be protected are stored in it while the
-smob does not yet competely exist and thus can not protect them.
+steps that allocate resources. Most of the time, this is mainly about
+allocating memory to hold associated data structures. Using memory
+managed by the garbage collector simplifies things: the garbage
+collector will automatically scan those data structures for pointers,
+and reclaim them when they are no longer referenced.
Continuing the example from above, if the global variable
@code{image_tag} contains a tag returned by @code{scm_make_smob_type},
/* Step 1: Allocate the memory block.
*/
- image = (struct image *) scm_gc_malloc (sizeof (struct image), "image");
+ image = (struct image *)
+ scm_gc_malloc (sizeof (struct image), "image");
/* Step 2: Initialize it with straight code.
*/
/* Step 3: Create the smob.
*/
- SCM_NEWSMOB (smob, image);
+ smob = scm_new_smob (image_tag, image);
/* Step 4: Finish the initialization.
*/
image->name = name;
- image->pixels = scm_gc_malloc (width * height, "image pixels");
+ image->pixels =
+ scm_gc_malloc_pointerless (width * height, "image pixels");
return smob;
@}
@end example
-Let us look at what might happen when @code{make_image} is called.
-
-The conversions of @var{s_width} and @var{s_height} to @code{int}s might
-fail and signal an error, thus causing a non-local exit. This is not a
-problem since no resources have been allocated yet that would have to be
-freed.
-
-The allocation of @var{image} in step 1 might fail, but this is likewise
-no problem.
-
-Step 2 can not exit non-locally. At the end of it, the @var{image}
-struct is in a valid state for the @code{mark_image} and
-@code{free_image} functions (see below).
-
-Step 3 can not exit non-locally either. This is guaranteed by Guile.
-After it, @var{smob} contains a valid smob that is properly initialized
-and protected, and in turn can properly protect the Scheme values in its
-@var{image} struct.
-
-But before the smob is completely created, @code{SCM_NEWSMOB} might
-cause the garbage collector to run. During this garbage collection, the
-@code{SCM} values in the @var{image} struct would be invisible to Guile.
-It only gets to know about them via the @code{mark_image} function, but
-that function can not yet do its job since the smob has not been created
-yet. Thus, it is important to not store @code{SCM} values in the
-@var{image} struct until after the smob has been created.
+We use @code{scm_gc_malloc_pointerless} for the pixel buffer to tell the
+garbage collector not to scan it for pointers. Calls to
+@code{scm_gc_malloc}, @code{scm_new_smob}, and
+@code{scm_gc_malloc_pointerless} raise an exception in out-of-memory
+conditions; the garbage collector is able to reclaim previously
+allocated memory if that happens.
-Step 4, finally, might fail and cause a non-local exit. In that case,
-the creation of the smob has not been successful. It will eventually be
-freed by the garbage collector, and all the resources that have been
-allocated for it will be correctly freed by @code{free_image}.
@node Type checking
@subsection Type checking
-Functions that operate on smobs should check that the passed @code{SCM}
-value indeed is a suitable smob before accessing its data.
+Functions that operate on smobs should check that the passed
+@code{SCM} value indeed is a suitable smob before accessing its data.
+They can do this with @code{scm_assert_smob_type}.
For example, here is a simple function that operates on an image smob,
and checks the type of its argument.
int area;
struct image *image;
- SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
- image_smob, SCM_ARG1, "clear-image");
+ scm_assert_smob_type (image_tag, image_smob);
image = (struct image *) SCM_SMOB_DATA (image_smob);
area = image->width * image->height;
@subsection Garbage Collecting Smobs
Once a smob has been released to the tender mercies of the Scheme
-system, it must be prepared to survive garbage collection. Guile calls
-the @emph{mark} and @emph{free} functions of the smob to manage this.
+system, it must be prepared to survive garbage collection. In the
+example above, all the memory associated with the smob is managed by the
+garbage collector because we used the @code{scm_gc_} allocation
+functions. Thus, no special care must be taken: the garbage collector
+automatically scans them and reclaims any unused memory.
+
+However, when data associated with a smob is managed in some other
+way---e.g., @code{malloc}'d memory or file descriptors---it is possible
+to specify a @emph{free} function to release those resources when the
+smob is reclaimed, and a @emph{mark} function to mark Scheme objects
+otherwise invisible to the garbage collector.
As described in more detail elsewhere (@pxref{Conservative GC}), every
object in the Scheme system has a @dfn{mark bit}, which the garbage
To mark an arbitrary Scheme object, the @emph{mark} function calls
@code{scm_gc_mark}.
-Thus, here is how we might write @code{mark_image}:
+Thus, here is how we might write @code{mark_image}---again this is not
+needed in our example since we used the @code{scm_gc_} allocation
+routines, so this is just for the sake of illustration:
@example
@group
integral type; the @emph{free} function should always return zero.
Here is how we might write the @code{free_image} function for the image
-smob type:
+smob type---again for the sake of illustration, since our example does
+not need it thanks to the use of the @code{scm_gc_} allocation routines:
@example
size_t
free_image (SCM image_smob)
@{
struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
- scm_gc_free (image->pixels, image->width * image->height, "image pixels");
+ scm_gc_free (image->pixels,
+ image->width * image->height,
+ "image pixels");
scm_gc_free (image, sizeof (struct image), "image");
return 0;
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.
functions very simple. Since collections occur at unpredictable times,
it is easy for any unusual activity to interfere with normal code.
-
-@node Garbage Collecting Simple Smobs
-@subsection Garbage Collecting Simple Smobs
-
-It is often useful to define very simple smob types --- smobs which have
-no data to mark, other than the cell itself, or smobs whose immediate
-data word is simply an ordinary Scheme object, to be marked recursively.
-Guile provides some functions to handle these common cases; you can use
-this function as your smob type's @emph{mark} function, if your smob's
-structure is simple enough.
-
-If the smob refers to no other Scheme objects, then no action is
-necessary; the garbage collector has already marked the smob cell
-itself. In that case, you can use zero as your mark function.
-
-@deftypefun SCM scm_markcdr (SCM @var{x})
-Mark the references in the smob @var{x}, assuming that @var{x}'s first
-data word contains an ordinary Scheme object, and @var{x} refers to no
-other objects. This function simply returns @var{x}'s first data word.
-
-This is only useful for simple smobs created by @code{SCM_NEWSMOB} or
-@code{SCM_RETURN_NEWSMOB}, not for smobs allocated as double cells.
-@end deftypefun
-
@node Remembering During Operations
@subsection Remembering During Operations
-@cindex Remembering
+@cindex remembering
+
+@c FIXME: Remove this section?
It's important that a smob is visible to the garbage collector
whenever its contents are being accessed. Otherwise it could be freed
struct image *image;
SCM lst;
int i;
- SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
- image_smob, SCM_ARG1, "image->list");
+
+ scm_assert_smob_type (image_tag, image_smob);
image = (struct image *) SCM_SMOB_DATA (image_smob);
lst = SCM_EOL;
@code{scm_remember_upto_here_1} will bite, but when it happens the
consequences are serious. Fortunately the rule is simple: whenever
calling a Guile library function or doing something that might, ensure
-the @code{SCM} of a smob is referenced past all accesses to its
+that 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.
@node Double Smobs
@subsection Double Smobs
+@c FIXME: Remove this section?
+
Smobs are called smob because they are small: they normally have only
-room for one @code{scm_t_bits} value plus 16 bits. The reason for
-this is that smobs are directly implemented by using the low-level,
-two-word cells of Guile that are also used to implement pairs, for
-example. (@pxref{Data Representation} for the details.) One word of
-the two-word cells is used for @code{SCM_SMOB_DATA}, the other
-contains the 16-bit type tag and the 16 extra bits.
+room for one @code{void*} or @code{SCM} value plus 16 bits. The
+reason for this is that smobs are directly implemented by using the
+low-level, two-word cells of Guile that are also used to implement
+pairs, for example. (@pxref{Data Representation} for the
+details.) One word of the two-word cells is used for
+@code{SCM_SMOB_DATA} (or @code{SCM_SMOB_OBJECT}), the other contains
+the 16-bit type tag and the 16 extra bits.
In addition to the fundamental two-word cells, Guile also has
four-word cells, which are appropriately called @dfn{double cells}.
You can use them for @dfn{double smobs} and get two more immediate
words of type @code{scm_t_bits}.
-A double smob is created with @code{SCM_NEWSMOB2} or
-@code{SCM_NEWSMOB3} instead of @code{SCM_NEWSMOB}. Its immediate
-words can be retrieved with @code{SCM_SMOB_DATA2} and
-@code{SCM_SMOB_DATA3} in addition to @code{SCM_SMOB_DATA}.
-Unsurprisingly, the words can be set with @code{SCM_SET_SMOB_DATA2}
-and @code{SCM_SET_SMOB_DATA3}.
+A double smob is created with @code{scm_new_double_smob}. Its immediate
+words can be retrieved as @code{scm_t_bits} with @code{SCM_SMOB_DATA_2}
+and @code{SCM_SMOB_DATA_3} in addition to @code{SCM_SMOB_DATA}.
+Unsurprisingly, the words can be set to @code{scm_t_bits} values with
+@code{SCM_SET_SMOB_DATA_2} and @code{SCM_SET_SMOB_DATA_3}.
+
+Of course there are also @code{SCM_SMOB_OBJECT_2},
+@code{SCM_SMOB_OBJECT_3}, @code{SCM_SET_SMOB_OBJECT_2}, and
+@code{SCM_SET_SMOB_OBJECT_3}.
@node The Complete Example
@subsection The Complete Example
/* Step 1: Allocate the memory block.
*/
- image = (struct image *) scm_gc_malloc (sizeof (struct image), "image");
+ image = (struct image *)
+ scm_gc_malloc (sizeof (struct image), "image");
/* Step 2: Initialize it with straight code.
*/
/* Step 3: Create the smob.
*/
- SCM_NEWSMOB (smob, image);
+ smob = scm_new_smob (image_tag, image);
/* Step 4: Finish the initialization.
*/
image->name = name;
- image->pixels = scm_gc_malloc (width * height, "image pixels");
+ image->pixels =
+ scm_gc_malloc (width * height, "image pixels");
return smob;
@}
int area;
struct image *image;
- SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
- image_smob, SCM_ARG1, "clear-image");
+ scm_assert_smob_type (image_tag, image_smob);
image = (struct image *) SCM_SMOB_DATA (image_smob);
area = image->width * image->height;
@{
struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
- scm_gc_free (image->pixels, image->width * image->height, "image pixels");
+ scm_gc_free (image->pixels,
+ image->width * image->height,
+ "image pixels");
scm_gc_free (image, sizeof (struct image), "image");
return 0;
@example
zwingli:example-smob$ make CC=gcc
-gcc `guile-config compile` -c image-type.c -o image-type.o
-gcc `guile-config compile` -c myguile.c -o myguile.o
-gcc image-type.o myguile.o `guile-config link` -o myguile
+gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` -c image-type.c -o image-type.o
+gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` -c myguile.c -o myguile.o
+gcc image-type.o myguile.o `pkg-config --libs guile-@value{EFFECTIVE-VERSION}` -o myguile
zwingli:example-smob$ ./myguile
guile> make-image
#<primitive-procedure make-image>
guile> (clear-image i)
guile> (clear-image 4)
ERROR: In procedure clear-image in expression (clear-image 4):
-ERROR: Wrong type argument in position 1: 4
+ERROR: Wrong type (expecting image): 4
ABORT: (wrong-type-arg)
Type "(backtrace)" to get more information.