1 /** @file
2 * @brief 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 #ifndef SEEN_INKSCAPE_GC_CORE_H
13 #define SEEN_INKSCAPE_GC_CORE_H
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
19 #include <new>
20 #include <cstdlib>
21 #include <cstddef>
22 #ifdef HAVE_GC_GC_H
23 # include <gc/gc.h>
24 #else
25 # include <gc.h>
26 #endif
27 #include <glib/gmain.h>
29 namespace Inkscape {
30 namespace GC {
32 enum ScanPolicy {
33 SCANNED,
34 ATOMIC
35 };
37 enum CollectionPolicy {
38 AUTO,
39 MANUAL
40 };
42 enum Delete {
43 GC
44 };
46 typedef void (*CleanupFunc)(void *mem, void *data);
48 struct Ops {
49 void (*do_init)();
50 void *(*malloc)(std::size_t size);
51 void *(*malloc_atomic)(std::size_t size);
52 void *(*malloc_uncollectable)(std::size_t size);
53 void *(*malloc_atomic_uncollectable)(std::size_t size);
54 void *(*base)(void *ptr);
55 void (*register_finalizer_ignore_self)(void *base,
56 CleanupFunc func, void *data,
57 CleanupFunc *old_func,
58 void **old_data);
59 int (*general_register_disappearing_link)(void **p_ptr,
60 void *base);
61 int (*unregister_disappearing_link)(void **p_ptr);
62 std::size_t (*get_heap_size)();
63 std::size_t (*get_free_bytes)();
64 void (*gcollect)();
65 void (*enable)();
66 void (*disable)();
67 void (*free)(void *ptr);
68 };
70 struct Core {
71 public:
72 static void init();
73 static inline void *malloc(std::size_t size) {
74 return _ops.malloc(size);
75 }
76 static inline void *malloc_atomic(std::size_t size) {
77 return _ops.malloc_atomic(size);
78 }
79 static inline void *malloc_uncollectable(std::size_t size) {
80 return _ops.malloc_uncollectable(size);
81 }
82 static inline void *malloc_atomic_uncollectable(std::size_t size) {
83 return _ops.malloc_atomic_uncollectable(size);
84 }
85 static inline void *base(void *ptr) {
86 return _ops.base(ptr);
87 }
88 static inline void register_finalizer_ignore_self(void *base,
89 CleanupFunc func,
90 void *data,
91 CleanupFunc *old_func,
92 void **old_data)
93 {
94 return _ops.register_finalizer_ignore_self(base, func, data,
95 old_func, old_data);
96 }
97 static inline int general_register_disappearing_link(void **p_ptr,
98 void *base)
99 {
100 return _ops.general_register_disappearing_link(p_ptr, base);
101 }
102 static inline int unregister_disappearing_link(void **p_ptr) {
103 return _ops.unregister_disappearing_link(p_ptr);
104 }
105 static inline std::size_t get_heap_size() {
106 return _ops.get_heap_size();
107 }
108 static inline std::size_t get_free_bytes() {
109 return _ops.get_free_bytes();
110 }
111 static inline void gcollect() {
112 _ops.gcollect();
113 }
114 static inline void enable() {
115 _ops.enable();
116 }
117 static inline void disable() {
118 _ops.disable();
119 }
120 static inline void free(void *ptr) {
121 return _ops.free(ptr);
122 }
123 private:
124 static Ops _ops;
125 };
127 inline void init() {
128 Core::init();
129 }
131 void request_early_collection();
133 }
134 }
136 inline void *operator new(std::size_t size,
137 Inkscape::GC::ScanPolicy scan,
138 Inkscape::GC::CollectionPolicy collect,
139 Inkscape::GC::CleanupFunc cleanup=NULL,
140 void *data=NULL)
141 throw(std::bad_alloc)
142 {
143 using namespace Inkscape::GC;
145 void *mem;
146 if ( collect == AUTO ) {
147 if ( scan == SCANNED ) {
148 mem = Core::malloc(size);
149 } else {
150 mem = Core::malloc_atomic(size);
151 }
152 } else {
153 if ( scan == SCANNED ) {
154 mem = Core::malloc_uncollectable(size);
155 } else {
156 mem = Core::malloc_atomic_uncollectable(size);
157 }
158 }
159 if (!mem) {
160 throw std::bad_alloc();
161 }
162 if (cleanup) {
163 Core::register_finalizer_ignore_self(mem, cleanup, data, NULL, NULL);
164 }
165 return mem;
166 }
168 inline void *operator new(std::size_t size,
169 Inkscape::GC::ScanPolicy scan,
170 Inkscape::GC::CleanupFunc cleanup=NULL,
171 void *data=NULL)
172 throw(std::bad_alloc)
173 {
174 return operator new(size, scan, Inkscape::GC::AUTO, cleanup, data);
175 }
177 inline void *operator new[](std::size_t size,
178 Inkscape::GC::ScanPolicy scan,
179 Inkscape::GC::CollectionPolicy collect,
180 Inkscape::GC::CleanupFunc cleanup=NULL,
181 void *data=NULL)
182 throw(std::bad_alloc)
183 {
184 return operator new(size, scan, collect, cleanup, data);
185 }
187 inline void *operator new[](std::size_t size,
188 Inkscape::GC::ScanPolicy scan,
189 Inkscape::GC::CleanupFunc cleanup=NULL,
190 void *data=NULL)
191 throw(std::bad_alloc)
192 {
193 return operator new[](size, scan, Inkscape::GC::AUTO, cleanup, data);
194 }
196 inline void operator delete(void *mem, Inkscape::GC::Delete) {
197 Inkscape::GC::Core::free(mem);
198 }
200 inline void operator delete[](void *mem, Inkscape::GC::Delete) {
201 operator delete(mem, Inkscape::GC::GC);
202 }
204 #endif
205 /*
206 Local Variables:
207 mode:c++
208 c-file-style:"stroustrup"
209 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
210 indent-tabs-mode:nil
211 fill-column:99
212 End:
213 */
214 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :