1 /* -*- Mode: C; c-basic-offset: 4 -*- */
2 /* guile-gnome
3  * Copyright (C) 2006 Andy Wingo <wingo at pobox dot com>
4  *
5  * gc.c: A sweep-safe replacement for scm_gc_protect_object
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, contact:
19  *
20  * Free Software Foundation           Voice:  +1-617-542-5942
21  * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
22  * Boston, MA  02111-1307,  USA       gnu@gnu.org
23  */
24 
25 
26 #include "guile-support.h"
27 #include "gc.h"
28 #include "gutil.h"
29 
30 
31 static GMutex *glib_gc_marker_hash_lock = NULL;
32 
33 static GHashTable *glib_gc_marker_hash = NULL;
34 
35 static SCM scm_sys_glib_gc_marker;
36 static scm_t_bits scm_tc16_glib_gc_marker;
37 
38 
39 /* #define DEBUG_PRINT */
40 
41 #ifdef DEBUG_PRINT
42 #define DEBUG_ALLOC(str, args...) g_print ("I: " str "\n", ##args)
43 #else
44 #define DEBUG_ALLOC(str, args...)
45 #endif
46 
47 
48 gpointer
scm_glib_gc_protect_object(SCM obj)49 scm_glib_gc_protect_object (SCM obj)
50 {
51     gpointer key = SCM_TO_GPOINTER (obj);
52     gpointer val;
53 
54     g_mutex_lock (glib_gc_marker_hash_lock);
55     val = g_hash_table_lookup (glib_gc_marker_hash, key);
56     g_hash_table_insert (glib_gc_marker_hash, key,
57                          GINT_TO_POINTER (GPOINTER_TO_INT (val)+1));
58     g_mutex_unlock (glib_gc_marker_hash_lock);
59 
60     return key;
61 }
62 
63 void
scm_glib_gc_unprotect_object(gpointer key)64 scm_glib_gc_unprotect_object (gpointer key)
65 {
66     gpointer val;
67 
68     g_mutex_lock (glib_gc_marker_hash_lock);
69     val = g_hash_table_lookup (glib_gc_marker_hash, key);
70     /* FIXME: is this right? */
71     if (val)
72         g_hash_table_insert (glib_gc_marker_hash, key,
73                              GINT_TO_POINTER (GPOINTER_TO_INT (val)-1));
74     else
75         g_hash_table_remove (glib_gc_marker_hash, key);
76     g_mutex_unlock (glib_gc_marker_hash_lock);
77 }
78 
79 static void
mark(gpointer key,gpointer val,gpointer user_data)80 mark (gpointer key, gpointer val, gpointer user_data)
81 {
82     scm_gc_mark (GPOINTER_TO_SCM (key));
83 }
84 
85 static SCM
glib_gc_marker_mark(SCM smob)86 glib_gc_marker_mark (SCM smob)
87 {
88     g_mutex_lock (glib_gc_marker_hash_lock);
89     g_hash_table_foreach (glib_gc_marker_hash, mark, NULL);
90     g_mutex_unlock (glib_gc_marker_hash_lock);
91 
92     return SCM_BOOL_F;
93 }
94 
95 static int
glib_gc_marker_print(SCM smob,SCM port,scm_print_state * print_state)96 glib_gc_marker_print (SCM smob, SCM port, scm_print_state *print_state)
97 {
98     scm_puts ("#<%glib-gc-marker>", port);
99     return 1;
100 }
101 
102 void
scm_init_gnome_gobject_gc(void)103 scm_init_gnome_gobject_gc (void)
104 {
105     scm_tc16_glib_gc_marker = scm_make_smob_type ("%glib-gc-marker", 0);
106     scm_set_smob_mark (scm_tc16_glib_gc_marker, glib_gc_marker_mark);
107     scm_set_smob_print (scm_tc16_glib_gc_marker, glib_gc_marker_print);
108 
109     if (!g_thread_supported ())
110         g_thread_init (NULL);
111 
112     glib_gc_marker_hash = g_hash_table_new (NULL, NULL);
113     glib_gc_marker_hash_lock = g_mutex_new ();
114 
115     SCM_NEWSMOB (scm_sys_glib_gc_marker, scm_tc16_glib_gc_marker, NULL);
116     scm_permanent_object (scm_sys_glib_gc_marker);
117 }
118