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