signal an error on multithreaded fork
[bpt/guile.git] / libguile / finalizers.c
CommitLineData
6e9ec86d
AW
1/* Copyright (C) 2012 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 */
18
19
20\f
21
22#ifdef HAVE_CONFIG_H
23# include <config.h>
24#endif
25
26#include "libguile/bdw-gc.h"
27#include "libguile/_scm.h"
28#include "libguile/finalizers.h"
29#include "libguile/gc.h"
30#include "libguile/threads.h"
31
32\f
33
34void
35scm_i_set_finalizer (void *obj, scm_t_finalizer_proc proc, void *data)
36{
37 GC_finalization_proc prev;
38 GC_PTR prev_data;
39 GC_REGISTER_FINALIZER_NO_ORDER (obj, proc, data, &prev, &prev_data);
40}
41
42struct scm_t_chained_finalizer
43{
44 int resuscitating_p;
45 scm_t_finalizer_proc proc;
46 void *data;
47 scm_t_finalizer_proc prev;
48 void *prev_data;
49};
50
51static void
52chained_finalizer (void *obj, void *data)
53{
54 struct scm_t_chained_finalizer *chained_data = data;
55 if (chained_data->resuscitating_p)
56 {
57 if (chained_data->prev)
58 scm_i_set_finalizer (obj, chained_data->prev, chained_data->prev_data);
59 chained_data->proc (obj, chained_data->data);
60 }
61 else
62 {
63 chained_data->proc (obj, chained_data->data);
64 if (chained_data->prev)
65 chained_data->prev (obj, chained_data->prev_data);
66 }
67}
68
69void
70scm_i_add_resuscitator (void *obj, scm_t_finalizer_proc proc, void *data)
71{
72 struct scm_t_chained_finalizer *chained_data;
73 chained_data = scm_gc_malloc (sizeof (*chained_data), "chained finalizer");
74 chained_data->resuscitating_p = 1;
75 chained_data->proc = proc;
76 chained_data->data = data;
77 GC_REGISTER_FINALIZER_NO_ORDER (obj, chained_finalizer, chained_data,
78 &chained_data->prev,
79 &chained_data->prev_data);
80}
81
82static void
83shuffle_resuscitators_to_front (struct scm_t_chained_finalizer *cd)
84{
85 while (cd->prev == chained_finalizer)
86 {
87 struct scm_t_chained_finalizer *prev = cd->prev_data;
88 scm_t_finalizer_proc proc = cd->proc;
89 void *data = cd->data;
90
91 if (!prev->resuscitating_p)
92 break;
93
94 cd->resuscitating_p = 1;
95 cd->proc = prev->proc;
96 cd->data = prev->data;
97
98 prev->resuscitating_p = 0;
99 prev->proc = proc;
100 prev->data = data;
101
102 cd = prev;
103 }
104}
105
106void
107scm_i_add_finalizer (void *obj, scm_t_finalizer_proc proc, void *data)
108{
109 struct scm_t_chained_finalizer *chained_data;
110 chained_data = scm_gc_malloc (sizeof (*chained_data), "chained finalizer");
111 chained_data->resuscitating_p = 0;
112 chained_data->proc = proc;
113 chained_data->data = data;
114 GC_REGISTER_FINALIZER_NO_ORDER (obj, chained_finalizer, chained_data,
115 &chained_data->prev,
116 &chained_data->prev_data);
117 shuffle_resuscitators_to_front (chained_data);
118}
119
120\f
121
122
123void
124scm_init_finalizers (void)
125{
126}