Include "libguile/async.h" for SCM_CRITICAL_SECTION_START/END.
[bpt/guile.git] / libguile / guardians.c
index fbecd9d..5ea3849 100644 (file)
@@ -1,46 +1,19 @@
-/*     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1998,1999,2000,2001 Free Software Foundation, Inc.
  * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA
- *
- * As a special exception, the Free Software Foundation gives permission
- * for additional uses of the text contained in its release of GUILE.
- *
- * The exception is that, if you link the GUILE library with other files
- * to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the GUILE library code into it.
- *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This exception applies only to the code released by the
- * Free Software Foundation under the name GUILE.  If you copy
- * code from other Free Software Foundation releases into a copy of
- * GUILE, as the General Public License permits, the exception does
- * not apply to the code that you add in this way.  To avoid misleading
- * anyone as to the status of such modified files, you must delete
- * this exception notice from them.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * If you write modifications of your own for GUILE, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.  */
-
-/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
-   gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
 
 \f
 
@@ -62,6 +35,7 @@
 
 
 #include "libguile/_scm.h"
+#include "libguile/async.h"
 #include "libguile/ports.h"
 #include "libguile/print.h"
 #include "libguile/smob.h"
    so that no synchronization between these needs to take place.
 */
 
-typedef struct tconc_t
+typedef struct t_tconc
 {
   SCM head;
   SCM tail;
-} tconc_t;
+} t_tconc;
 
-#define TCONC_EMPTYP(tc) (SCM_EQ_P ((tc).head, (tc).tail))
+#define TCONC_EMPTYP(tc) (scm_is_eq ((tc).head, (tc).tail))
 
 #define TCONC_IN(tc, obj, pair) \
 do { \
   SCM_SETCAR ((tc).tail, obj); \
-  SCM_SETCAR (pair, SCM_BOOL_F); \
-  SCM_SETCDR (pair, SCM_EOL); \
+  SCM_SET_CELL_OBJECT_1 (pair, SCM_EOL); \
+  SCM_SET_CELL_OBJECT_0 (pair, SCM_BOOL_F); \
   SCM_SETCDR ((tc).tail, pair); \
   (tc).tail = pair; \
 } while (0)
@@ -102,18 +76,18 @@ do { \
 } while (0)
 
 
-static scm_bits_t tc16_guardian;
+static scm_t_bits tc16_guardian;
 
-typedef struct guardian_t
+typedef struct t_guardian
 {
-  tconc_t live;
-  tconc_t zombies;
-  struct guardian_t *next;
+  t_tconc live;
+  t_tconc zombies;
+  struct t_guardian *next;
   unsigned long flags;
-} guardian_t;
+} t_guardian;
 
 #define GUARDIAN_P(x) SCM_SMOB_PREDICATE(tc16_guardian, x)
-#define GUARDIAN(x) ((guardian_t *) SCM_CELL_WORD_1 (x))
+#define GUARDIAN_DATA(x) ((t_guardian *) SCM_CELL_WORD_1 (x))
 
 #define F_GREEDY 1L
 #define F_LISTED (1L << 1)
@@ -131,8 +105,8 @@ typedef struct guardian_t
 
 /* during the gc mark phase, live guardians are linked into the lists
    here. */
-static guardian_t *greedy_guardians = NULL;
-static guardian_t *sharing_guardians = NULL;
+static t_guardian *greedy_guardians = NULL;
+static t_guardian *sharing_guardians = NULL;
 
 static SCM greedily_guarded_whash = SCM_EOL;
 
@@ -143,7 +117,7 @@ static SCM self_centered_zombies = SCM_EOL;
 
 
 static void
-add_to_live_list (guardian_t *g)
+add_to_live_list (t_guardian *g)
 {
   if (LISTED_P (g))
     return;
@@ -166,7 +140,7 @@ add_to_live_list (guardian_t *g)
 static SCM
 guardian_mark (SCM ptr)
 {
-  add_to_live_list (GUARDIAN (ptr));
+  add_to_live_list (GUARDIAN_DATA (ptr));
 
   /* the objects protected by the guardian are not marked here: that
      would prevent them from ever getting collected.  instead marking
@@ -175,18 +149,18 @@ guardian_mark (SCM ptr)
 }
 
 
-static scm_sizet
+static size_t
 guardian_free (SCM ptr)
 {
-  scm_must_free (GUARDIAN (ptr));
-  return sizeof (guardian_t);
+  scm_gc_free (GUARDIAN_DATA (ptr), sizeof (t_guardian), "guardian");
+  return 0;
 }
 
 
 static int
-guardian_print (SCM guardian, SCM port, scm_print_state *pstate)
+guardian_print (SCM guardian, SCM port, scm_print_state *pstate SCM_UNUSED)
 {
-  guardian_t *g = GUARDIAN (guardian);
+  t_guardian *g = GUARDIAN_DATA (guardian);
   
   scm_puts ("#<", port);
   
@@ -199,7 +173,7 @@ guardian_print (SCM guardian, SCM port, scm_print_state *pstate)
     scm_puts ("sharing", port);
 
   scm_puts (" guardian 0x", port);
-  scm_intprint ((long) g, 16, port);
+  scm_uintprint ((scm_t_bits) g, 16, port);
 
   if (! DESTROYED_P (g))
     {
@@ -228,15 +202,15 @@ guardian_print (SCM guardian, SCM port, scm_print_state *pstate)
 static SCM
 guardian_apply (SCM guardian, SCM obj, SCM throw_p)
 {
-  if (DESTROYED_P (GUARDIAN (guardian)))
+  if (DESTROYED_P (GUARDIAN_DATA (guardian)))
     scm_misc_error ("guard", "attempted use of destroyed guardian: ~A",
-                    SCM_LIST1 (guardian));
+                    scm_list_1 (guardian));
   
   if (!SCM_UNBNDP (obj))
     return scm_guard (guardian, obj,
                       (SCM_UNBNDP (throw_p)
                        ? 1
-                       : SCM_NFALSEP (throw_p)));
+                       : scm_is_true (throw_p)));
   else
     return scm_get_one_zombie (guardian);
 }
@@ -245,28 +219,26 @@ guardian_apply (SCM guardian, SCM obj, SCM throw_p)
 SCM
 scm_guard (SCM guardian, SCM obj, int throw_p)
 {
-  guardian_t *g = GUARDIAN (guardian);
+  t_guardian *g = GUARDIAN_DATA (guardian);
   
   if (!SCM_IMP (obj))
     {
       SCM z;
 
-      SCM_NEWCELL (z);
-      
       /* This critical section barrier will be replaced by a mutex. */
-      SCM_DEFER_INTS;
+      SCM_CRITICAL_SECTION_START;
 
       if (GREEDY_P (g))
         {
-          if (SCM_NFALSEP (scm_hashq_get_handle
+          if (scm_is_true (scm_hashq_get_handle
                            (greedily_guarded_whash, obj)))
             {
-              SCM_ALLOW_INTS;
+              SCM_CRITICAL_SECTION_END;
 
               if (throw_p)
                 scm_misc_error ("guard",
                                 "object is already greedily guarded: ~A",
-                                SCM_LIST1 (obj));
+                                scm_list_1 (obj));
               else
                 return SCM_BOOL_F;
             }
@@ -275,33 +247,32 @@ scm_guard (SCM guardian, SCM obj, int throw_p)
                                        obj, guardian);
         }
 
+      z = scm_cons (SCM_BOOL_F, SCM_BOOL_F);
       TCONC_IN (g->live, obj, z);
 
-      SCM_ALLOW_INTS;
+      SCM_CRITICAL_SECTION_END;
     }
 
   return throw_p ? SCM_UNSPECIFIED : SCM_BOOL_T;
-
 }
 
 
 SCM
 scm_get_one_zombie (SCM guardian)
 {
-  guardian_t *g = GUARDIAN (guardian);
+  t_guardian *g = GUARDIAN_DATA (guardian);
   SCM res = SCM_BOOL_F;
 
   /* This critical section barrier will be replaced by a mutex. */
-  SCM_DEFER_INTS;
+  SCM_CRITICAL_SECTION_START;
 
   if (!TCONC_EMPTYP (g->zombies))
     TCONC_OUT (g->zombies, res);
 
-  if (SCM_NFALSEP (res)
-      && GREEDY_P (g))
+  if (scm_is_true (res) && GREEDY_P (g))
     scm_hashq_remove_x (greedily_guarded_whash, res);
 
-  SCM_ALLOW_INTS;
+  SCM_CRITICAL_SECTION_END;
   
   return res;
 }
@@ -336,7 +307,7 @@ SCM_DEFINE (scm_make_guardian, "make-guardian", 0, 1, 0,
             "paper still (mostly) accurately describes the interface).")
 #define FUNC_NAME s_scm_make_guardian
 {
-  guardian_t *g = SCM_MUST_MALLOC_TYPE (guardian_t);
+  t_guardian *g = scm_gc_malloc (sizeof (t_guardian), "guardian");
   SCM z1 = scm_cons (SCM_BOOL_F, SCM_EOL);
   SCM z2 = scm_cons (SCM_BOOL_F, SCM_EOL);
   SCM z;
@@ -349,7 +320,7 @@ SCM_DEFINE (scm_make_guardian, "make-guardian", 0, 1, 0,
   g->flags = 0L;
 
   /* [cmm] the UNBNDP check below is redundant but I like it. */
-  if (SCM_UNBNDP (greedy_p) || SCM_NFALSEP (greedy_p))
+  if (SCM_UNBNDP (greedy_p) || scm_is_true (greedy_p))
     SET_GREEDY (g);
   
   SCM_NEWSMOB (z, tc16_guardian, g);
@@ -367,11 +338,11 @@ SCM_DEFINE (scm_guardian_destroyed_p, "guardian-destroyed?", 1, 0, 0,
   SCM res = SCM_BOOL_F;
 
   /* This critical section barrier will be replaced by a mutex. */
-  SCM_DEFER_INTS;
+  SCM_CRITICAL_SECTION_START;
 
-  res = SCM_BOOL (DESTROYED_P (GUARDIAN (guardian)));
+  res = scm_from_bool (DESTROYED_P (GUARDIAN_DATA (guardian)));
   
-  SCM_ALLOW_INTS;
+  SCM_CRITICAL_SECTION_END;
 
   return res;
 }
@@ -379,10 +350,10 @@ SCM_DEFINE (scm_guardian_destroyed_p, "guardian-destroyed?", 1, 0, 0,
 
 SCM_DEFINE (scm_guardian_greedy_p, "guardian-greedy?", 1, 0, 0,
             (SCM guardian),
-            "Return @code{#t} if @var{guardian} is a greedy guardian, otherwise @code{#f}.\n")
+            "Return @code{#t} if @var{guardian} is a greedy guardian, otherwise @code{#f}.")
 #define FUNC_NAME s_scm_guardian_greedy_p  
 {
-  return SCM_BOOL (GREEDY_P (GUARDIAN (guardian)));
+  return scm_from_bool (GREEDY_P (GUARDIAN_DATA (guardian)));
 }
 #undef FUNC_NAME
 
@@ -393,15 +364,16 @@ SCM_DEFINE (scm_destroy_guardian_x, "destroy-guardian!", 1, 0, 0,
             "objects guarded by @var{guardian}.")
 #define FUNC_NAME s_scm_destroy_guardian_x
 {
-  guardian_t *g = GUARDIAN (guardian);
+  t_guardian *g = GUARDIAN_DATA (guardian);
 
   /* This critical section barrier will be replaced by a mutex. */
-  SCM_DEFER_INTS;
+  SCM_CRITICAL_SECTION_START;
   
   if (DESTROYED_P (g))
     {
-      SCM_ALLOW_INTS;
-      SCM_MISC_ERROR ("guardian is already destroyed: ~A", SCM_LIST1 (guardian));
+      SCM_CRITICAL_SECTION_END;
+      SCM_MISC_ERROR ("guardian is already destroyed: ~A",
+                     scm_list_1 (guardian));
     }
 
   if (GREEDY_P (g))
@@ -420,7 +392,7 @@ SCM_DEFINE (scm_destroy_guardian_x, "destroy-guardian!", 1, 0, 0,
   
   SET_DESTROYED (g);
   
-  SCM_ALLOW_INTS;
+  SCM_CRITICAL_SECTION_END;
 
   return SCM_UNSPECIFIED;
 }
@@ -428,7 +400,9 @@ SCM_DEFINE (scm_destroy_guardian_x, "destroy-guardian!", 1, 0, 0,
             
 /* called before gc mark phase begins to initialise the live guardian list. */
 static void *
-guardian_gc_init (void *dummy1, void *dummy2, void *dummy3)
+guardian_gc_init (void *dummy1 SCM_UNUSED,
+                 void *dummy2 SCM_UNUSED,
+                 void *dummy3 SCM_UNUSED)
 {
   greedy_guardians = sharing_guardians = NULL;
 
@@ -436,7 +410,7 @@ guardian_gc_init (void *dummy1, void *dummy2, void *dummy3)
 }
 
 static void
-mark_dependencies_in_tconc (tconc_t *tc)
+mark_dependencies_in_tconc (t_tconc *tc)
 {
   SCM pair, next_pair;
   SCM *prev_ptr;
@@ -444,34 +418,34 @@ mark_dependencies_in_tconc (tconc_t *tc)
   /* scan the list for unmarked objects, and mark their
      dependencies */
   for (pair = tc->head, prev_ptr = &tc->head;
-       ! SCM_EQ_P (pair, tc->tail);
+       !scm_is_eq (pair, tc->tail);
        pair = next_pair)
     {
       SCM obj = SCM_CAR (pair);
       next_pair = SCM_CDR (pair);
             
-      if (! SCM_MARKEDP (obj))
+      if (! SCM_GC_MARK_P (obj))
         {
           /* a candidate for finalizing */
           scm_gc_mark_dependencies (obj);
 
-          if (SCM_MARKEDP (obj))
+          if (SCM_GC_MARK_P (obj))
             {
               /* uh oh.  a cycle.  transfer this object (the
                  spine cell, to be exact) to
                  self_centered_zombies, so we'll be able to
                  complain about it later. */
               *prev_ptr = next_pair;
-              SCM_SETGCMARK (pair);
-              SCM_SETCDR (pair, SCM_CDR (self_centered_zombies));
-              SCM_SETCDR (self_centered_zombies, pair);
+              SCM_SET_GC_MARK (pair);
+              SCM_SETCDR (pair, self_centered_zombies);
+              self_centered_zombies = pair;
             }
           else
             {
               /* see if this is a guardian.  if yes, list it (but don't   
                  mark it yet). */
               if (GUARDIAN_P (obj))
-                add_to_live_list (GUARDIAN (obj));
+                add_to_live_list (GUARDIAN_DATA (obj));
 
               prev_ptr = SCM_CDRLOC (pair);
             }
@@ -480,24 +454,24 @@ mark_dependencies_in_tconc (tconc_t *tc)
 }
 
 static void
-mark_dependencies (guardian_t *g)
+mark_dependencies (t_guardian *g)
 {
   mark_dependencies_in_tconc (&g->zombies);
   mark_dependencies_in_tconc (&g->live);
 }
 
 static void
-mark_and_zombify (guardian_t *g)
+mark_and_zombify (t_guardian *g)
 {
   SCM tconc_tail = g->live.tail;
   SCM *prev_ptr = &g->live.head;
   SCM pair = g->live.head;
 
-  while (! SCM_EQ_P (pair, tconc_tail))
+  while (!scm_is_eq (pair, tconc_tail))
     {
       SCM next_pair = SCM_CDR (pair);
 
-      if (SCM_NMARKEDP (SCM_CAR (pair)))
+      if (!SCM_GC_MARK_P (SCM_CAR (pair)))
         {
           /* got you, zombie! */
 
@@ -507,7 +481,7 @@ mark_and_zombify (guardian_t *g)
           if (GREEDY_P (g))
             /* if the guardian is greedy, mark this zombie now.  this
                way it won't be zombified again this time around. */
-            SCM_SETGCMARK (SCM_CAR (pair));
+            SCM_SET_GC_MARK (SCM_CAR (pair));
 
           /* into the zombie list! */
           TCONC_IN (g->zombies, SCM_CAR (pair), pair);
@@ -521,8 +495,8 @@ mark_and_zombify (guardian_t *g)
   /* Mark the cells of the live list (yes, the cells in the list, we
      don't care about objects pointed to by the list cars, since we
      know they are already marked).  */
-  for (pair = g->live.head; !SCM_NULLP (pair); pair = SCM_CDR (pair))
-    SCM_SETGCMARK (pair);
+  for (pair = g->live.head; !scm_is_null (pair); pair = SCM_CDR (pair))
+    SCM_SET_GC_MARK (pair);
 }
 
 
@@ -530,13 +504,15 @@ mark_and_zombify (guardian_t *g)
    phases.  for each marked guardian, it moves any unmarked object in
    its live list (tconc) to its zombie list (tconc).  */
 static void *
-guardian_zombify (void *dummy1, void *dummy2, void *dummy3)
+guardian_zombify (void *dummy1 SCM_UNUSED,
+                 void *dummy2 SCM_UNUSED,
+                 void *dummy3 SCM_UNUSED)
 {
-  guardian_t *last_greedy_guardian = NULL;
-  guardian_t *last_sharing_guardian = NULL;
-  guardian_t *first_greedy_guardian = NULL;
-  guardian_t *first_sharing_guardian = NULL;
-  guardian_t *g;
+  t_guardian *last_greedy_guardian = NULL;
+  t_guardian *last_sharing_guardian = NULL;
+  t_guardian *first_greedy_guardian = NULL;
+  t_guardian *first_sharing_guardian = NULL;
+  t_guardian *g;
 
   /* First, find all newly unreachable objects and mark their
      dependencies.
@@ -588,23 +564,26 @@ guardian_zombify (void *dummy1, void *dummy2, void *dummy3)
 }
 
 static void *
-whine_about_self_centered_zombies (void *dummy1, void *dummy2, void *dummy3)
+whine_about_self_centered_zombies (void *dummy1 SCM_UNUSED,
+                                  void *dummy2 SCM_UNUSED,
+                                  void *dummy3 SCM_UNUSED)
 {
-  if (! SCM_NULLP (SCM_CDR (self_centered_zombies)))
+  if (!scm_is_null (self_centered_zombies))
     {
+      SCM port = scm_current_error_port ();
       SCM pair;
       
       scm_puts ("** WARNING: the following guarded objects were unguarded due to cycles:",
-                scm_cur_errp);
-      scm_newline (scm_cur_errp);
-      for (pair = SCM_CDR (self_centered_zombies);
-           ! SCM_NULLP (pair); pair = SCM_CDR (pair))
+                port);
+      scm_newline (port);
+      for (pair = self_centered_zombies;
+           !scm_is_null (pair); pair = SCM_CDR (pair))
         {
-          scm_display (SCM_CAR (pair), scm_cur_errp);
-          scm_newline (scm_cur_errp);
+          scm_display (SCM_CAR (pair), port);
+          scm_newline (port);
         }
 
-      SCM_SETCDR (self_centered_zombies, SCM_EOL);
+      self_centered_zombies = SCM_EOL;
     }
   
   return 0;
@@ -622,17 +601,14 @@ scm_init_guardians ()
   scm_c_hook_add (&scm_before_mark_c_hook, guardian_gc_init, 0, 0);
   scm_c_hook_add (&scm_before_sweep_c_hook, guardian_zombify, 0, 0);
 
-  self_centered_zombies =
-    scm_permanent_object (scm_cons (SCM_UNDEFINED, SCM_EOL));
+  scm_gc_register_root (&self_centered_zombies);
   scm_c_hook_add (&scm_after_gc_c_hook,
                   whine_about_self_centered_zombies, 0, 0);
 
   greedily_guarded_whash =
-    scm_permanent_object (scm_make_doubly_weak_hash_table (SCM_MAKINUM (31)));
+    scm_permanent_object (scm_make_doubly_weak_hash_table (scm_from_int (31)));
 
-#ifndef SCM_MAGIC_SNARFER
 #include "libguile/guardians.x"
-#endif
 }
 
 /*