Code

* src/dialogs/layers-panel.cpp: Compile fix from Mathieu Dimanche.
[inkscape.git] / src / gc.cpp
1 /*
2  * Inkscape::GC - Wrapper for Boehm GC
3  *
4  * Authors:
5  *   MenTaLguY <mental@rydia.net>
6  *
7  * Copyright (C) 2004 MenTaLguY
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #include "gc-core.h"
13 #include <stdexcept>
14 #include <glib/gmessages.h>
16 namespace Inkscape {
17 namespace GC {
19 namespace {
21 void display_warning(char *msg, GC_word arg) {
22     g_warning(msg, arg);
23 }
25 void do_init() {
26     GC_no_dls = 1;
27     GC_all_interior_pointers = 1;
28     GC_finalize_on_demand = 0;
30     GC_INIT();
32     GC_set_warn_proc(&display_warning);
33 }
35 void *debug_malloc(std::size_t size) {
36     return GC_debug_malloc(size, GC_EXTRAS);
37 }
39 void *debug_malloc_atomic(std::size_t size) {
40     return GC_debug_malloc_atomic(size, GC_EXTRAS);
41 }
43 void *debug_malloc_uncollectable(std::size_t size) {
44     return GC_debug_malloc_uncollectable(size, GC_EXTRAS);
45 }
47 void *debug_malloc_atomic_uncollectable(std::size_t size) {
48     return GC_debug_malloc_uncollectable(size, GC_EXTRAS);
49 }
51 std::ptrdiff_t compute_debug_base_fixup() {
52     char *base=reinterpret_cast<char *>(GC_debug_malloc(1, GC_EXTRAS));
53     char *real_base=reinterpret_cast<char *>(GC_base(base));
54     GC_debug_free(base);
55     return base - real_base;
56 }
58 inline std::ptrdiff_t const &debug_base_fixup() {
59     static std::ptrdiff_t fixup=compute_debug_base_fixup();
60     return fixup;
61 }
63 void *debug_base(void *ptr) {
64     char *base=reinterpret_cast<char *>(GC_base(ptr));
65     return base + debug_base_fixup();
66 }
68 int debug_general_register_disappearing_link(void **p_ptr, void *base) {
69     char *real_base=reinterpret_cast<char *>(base) - debug_base_fixup();
70     return GC_general_register_disappearing_link(p_ptr, real_base);
71 }
73 void dummy_do_init() {}
75 void *dummy_base(void *) { return NULL; }
77 void dummy_register_finalizer(void *, CleanupFunc, void *,
78                                       CleanupFunc *old_func, void **old_data)
79 {
80     if (old_func) {
81         *old_func = NULL;
82     }
83     if (old_data) {
84         *old_data = NULL;
85     }
86 }
88 int dummy_general_register_disappearing_link(void **, void *) { return false; }
90 int dummy_unregister_disappearing_link(void **link) { return false; }
92 std::size_t dummy_get_heap_size() { return 0; }
94 std::size_t dummy_get_free_bytes() { return 0; }
96 void dummy_gcollect() {}
98 void dummy_enable() {}
100 void dummy_disable() {}
102 Ops enabled_ops = {
103     &do_init,
104     &GC_malloc,
105     &GC_malloc_atomic,
106     &GC_malloc_uncollectable,
107     &GC_malloc_atomic_uncollectable,
108     &GC_base,
109     &GC_register_finalizer_ignore_self,
110     &GC_general_register_disappearing_link,
111     &GC_unregister_disappearing_link,
112     &GC_get_heap_size,
113     &GC_get_free_bytes,
114     &GC_gcollect,
115     &GC_enable,
116     &GC_disable,
117     &GC_free
118 };
120 Ops debug_ops = {
121     &do_init,
122     &debug_malloc,
123     &debug_malloc_atomic,
124     &debug_malloc_uncollectable,
125     &debug_malloc_atomic_uncollectable,
126     &debug_base,
127     &GC_debug_register_finalizer_ignore_self,
128     &debug_general_register_disappearing_link,
129     &GC_unregister_disappearing_link,
130     &GC_get_heap_size,
131     &GC_get_free_bytes,
132     &GC_gcollect,
133     &GC_enable,
134     &GC_disable,
135     &GC_debug_free
136 };
138 Ops disabled_ops = {
139     &dummy_do_init,
140     &std::malloc,
141     &std::malloc,
142     &std::malloc,
143     &std::malloc,
144     &dummy_base,
145     &dummy_register_finalizer,
146     &dummy_general_register_disappearing_link,
147     &dummy_unregister_disappearing_link,
148     &dummy_get_heap_size,
149     &dummy_get_free_bytes,
150     &dummy_gcollect,
151     &dummy_enable,
152     &dummy_disable,
153     &std::free
154 };
156 class InvalidGCModeError : public std::runtime_error {
157 public:
158     InvalidGCModeError(const char *mode)
159     : runtime_error(std::string("Unknown GC mode \"") + mode + "\"")
160     {}
161 };
163 Ops const &get_ops() throw (InvalidGCModeError) {
164     char *mode_string=std::getenv("_INKSCAPE_GC");
165     if (mode_string) {
166         if (!std::strcmp(mode_string, "enable")) {
167             return enabled_ops;
168         } else if (!std::strcmp(mode_string, "debug")) {
169             return debug_ops;
170         } else if (!std::strcmp(mode_string, "disable")) {
171             return disabled_ops;
172         } else {
173             throw InvalidGCModeError(mode_string);
174         }
175     } else {
176         return enabled_ops;
177     }
180 void die_because_not_initialized() {
181     g_error("Attempt to use GC allocator before call to Inkscape::GC::init()");
184 void *stub_malloc(std::size_t) {
185     die_because_not_initialized();
186     return NULL;
189 void *stub_base(void *) {
190     die_because_not_initialized();
191     return NULL;
194 void stub_register_finalizer_ignore_self(void *, CleanupFunc, void *,
195                                                  CleanupFunc *, void **)
197     die_because_not_initialized();
200 int stub_general_register_disappearing_link(void **, void *) {
201     die_because_not_initialized();
202     return 0;
205 int stub_unregister_disappearing_link(void **) {
206     die_because_not_initialized();
207     return 0;
210 std::size_t stub_get_heap_size() {
211     die_because_not_initialized();
212     return 0;
215 std::size_t stub_get_free_bytes() {
216     die_because_not_initialized();
217     return 0;
220 void stub_gcollect() {
221     die_because_not_initialized();
224 void stub_enable() {
225     die_because_not_initialized();
228 void stub_disable() {
229     die_because_not_initialized();
232 void stub_free(void *) {
233     die_because_not_initialized();
238 Ops Core::_ops = {
239     NULL,
240     &stub_malloc,
241     &stub_malloc,
242     &stub_malloc,
243     &stub_malloc,
244     &stub_base,
245     &stub_register_finalizer_ignore_self,
246     &stub_general_register_disappearing_link,
247     &stub_unregister_disappearing_link,
248     &stub_get_heap_size,
249     &stub_get_free_bytes,
250     &stub_gcollect,
251     &stub_enable,
252     &stub_disable,
253     &stub_free
254 };
256 void Core::init() {
257     try {
258         _ops = get_ops();
259     } catch (InvalidGCModeError &e) {
260         g_warning("%s; enabling normal collection", e.what());
261         _ops = enabled_ops;
262     }
264     _ops.do_init();
270 /*
271   Local Variables:
272   mode:c++
273   c-file-style:"stroustrup"
274   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
275   indent-tabs-mode:nil
276   fill-column:99
277   End:
278 */
279 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :