18#include <sigc++/functors/ptr_fun.h>
19#include <glibmm/main.h>
27void display_warning(
char *
msg, GC_word arg) {
33 GC_set_all_interior_pointers(1);
34 GC_set_finalize_on_demand(0);
38 GC_set_warn_proc(&display_warning);
41void *debug_malloc(std::size_t
size) {
42 return GC_debug_malloc(
size, GC_EXTRAS);
45void *debug_malloc_atomic(std::size_t
size) {
46 return GC_debug_malloc_atomic(
size, GC_EXTRAS);
49void *debug_malloc_uncollectable(std::size_t
size) {
50 return GC_debug_malloc_uncollectable(
size, GC_EXTRAS);
53void *debug_malloc_atomic_uncollectable(std::size_t
size) {
54 return GC_debug_malloc_uncollectable(
size, GC_EXTRAS);
57std::ptrdiff_t compute_debug_base_fixup() {
58 char *base=
reinterpret_cast<char *
>(GC_debug_malloc(1, GC_EXTRAS));
59 char *real_base=
reinterpret_cast<char *
>(GC_base(base));
61 return base - real_base;
64inline std::ptrdiff_t
const &debug_base_fixup() {
65 static std::ptrdiff_t fixup=compute_debug_base_fixup();
69void *debug_base(
void *ptr) {
70 char *base=
reinterpret_cast<char *
>(GC_base(ptr));
71 return base + debug_base_fixup();
74int debug_general_register_disappearing_link(
void **p_ptr,
void const *base) {
75 char const *real_base =
reinterpret_cast<char const *
>(base) - debug_base_fixup();
76#if (GC_MAJOR_VERSION >= 7 && GC_MINOR_VERSION >= 4)
77 return GC_general_register_disappearing_link(p_ptr, real_base);
79 return GC_general_register_disappearing_link(p_ptr,
const_cast<char *
>(real_base));
83void dummy_do_init() {}
85void *dummy_base(
void *) {
return nullptr; }
87void dummy_register_finalizer(
void *,
CleanupFunc,
void *,
98int dummy_general_register_disappearing_link(
void **,
void const *) {
return false; }
100int dummy_unregister_disappearing_link(
void **) {
return false; }
102std::size_t dummy_get_heap_size() {
return 0; }
104std::size_t dummy_get_free_bytes() {
return 0; }
106void dummy_gcollect() {}
108void dummy_enable() {}
110void dummy_disable() {}
116 &GC_malloc_uncollectable,
117 &GC_malloc_atomic_uncollectable,
119 &GC_register_finalizer_ignore_self,
120#if (GC_MAJOR_VERSION >= 7 && GC_MINOR_VERSION >= 4)
121 &GC_general_register_disappearing_link,
123 (int (*)(
void**,
const void*))(&GC_general_register_disappearing_link),
125 &GC_unregister_disappearing_link,
137 &debug_malloc_atomic,
138 &debug_malloc_uncollectable,
139 &debug_malloc_atomic_uncollectable,
141 &GC_debug_register_finalizer_ignore_self,
142 &debug_general_register_disappearing_link,
143 &GC_unregister_disappearing_link,
159 &dummy_register_finalizer,
160 &dummy_general_register_disappearing_link,
161 &dummy_unregister_disappearing_link,
162 &dummy_get_heap_size,
163 &dummy_get_free_bytes,
170class InvalidGCModeError :
public std::runtime_error {
172 InvalidGCModeError(
const char *
mode)
173 : runtime_error(
std::string(
"Unknown GC mode \"") +
mode +
"\"")
177Ops
const &get_ops() {
178 char *mode_string=std::getenv(
"_INKSCAPE_GC");
180 if (!std::strcmp(mode_string,
"enable")) {
182 }
else if (!std::strcmp(mode_string,
"debug")) {
184 }
else if (!std::strcmp(mode_string,
"disable")) {
187 throw InvalidGCModeError(mode_string);
194void die_because_not_initialized() {
195 g_error(
"Attempt to use GC allocator before call to Inkscape::GC::init()");
198void *stub_malloc(std::size_t) {
199 die_because_not_initialized();
203void *stub_base(
void *) {
204 die_because_not_initialized();
208void stub_register_finalizer_ignore_self(
void *,
CleanupFunc,
void *,
211 die_because_not_initialized();
214int stub_general_register_disappearing_link(
void **,
void const *) {
215 die_because_not_initialized();
219int stub_unregister_disappearing_link(
void **) {
220 die_because_not_initialized();
224std::size_t stub_get_heap_size() {
225 die_because_not_initialized();
229std::size_t stub_get_free_bytes() {
230 die_because_not_initialized();
234void stub_gcollect() {
235 die_because_not_initialized();
239 die_because_not_initialized();
243 die_because_not_initialized();
246void stub_free(
void *) {
247 die_because_not_initialized();
259 &stub_register_finalizer_ignore_self,
260 &stub_general_register_disappearing_link,
261 &stub_unregister_disappearing_link,
263 &stub_get_free_bytes,
273 }
catch (InvalidGCModeError &e) {
274 g_warning(
"%s; enabling normal collection", e.what());
284bool collection_requested=
false;
285bool collection_task() {
288 collection_requested=
false;
295 if (!collection_requested) {
296 collection_requested=
true;
297 Glib::signal_idle().connect(sigc::ptr_fun(&collection_task));
void(* CleanupFunc)(void *mem, void *data)
void request_early_collection()
Helper class to stream background task notifications as a series of messages.