summaryrefslogtreecommitdiffstats
path: root/src/libgc
diff options
context:
space:
mode:
authorLiam P. White <inkscapebrony@gmail.com>2015-02-25 22:24:47 +0000
committerLiam P. White <inkscapebrony@gmail.com>2015-02-25 22:24:47 +0000
commit5865f0044d4d75a2d988a8bf2ea3bc65ed6f4c18 (patch)
treebabbe1ec041ee27dc0885e5d15a0e135de49e24a /src/libgc
parentRemove useless file (diff)
downloadinkscape-5865f0044d4d75a2d988a8bf2ea3bc65ed6f4c18.tar.gz
inkscape-5865f0044d4d75a2d988a8bf2ea3bc65ed6f4c18.zip
Isolate components of libgc
(bzr r13946)
Diffstat (limited to 'src/libgc')
-rw-r--r--src/libgc/CMakeLists.txt15
-rw-r--r--src/libgc/Makefile_insert13
-rw-r--r--src/libgc/gc-alloc.h90
-rw-r--r--src/libgc/gc-core.h213
-rw-r--r--src/libgc/gc-managed.h63
-rw-r--r--src/libgc/gc-soft-ptr.h70
-rw-r--r--src/libgc/gc.cpp312
7 files changed, 776 insertions, 0 deletions
diff --git a/src/libgc/CMakeLists.txt b/src/libgc/CMakeLists.txt
new file mode 100644
index 000000000..22dd464e1
--- /dev/null
+++ b/src/libgc/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+set(libgc_SRC
+ gc.cpp
+
+ # -------
+ # Headers
+ gc-alloc.h
+ gc-anchored.h
+ gc-core.h
+ gc-managed.h
+ gc-soft-ptr.h
+)
+
+add_inkscape_lib(gc_LIB "${libgc_SRC}")
+# add_inkscape_source("${libgc_SRC}")
diff --git a/src/libgc/Makefile_insert b/src/libgc/Makefile_insert
new file mode 100644
index 000000000..e899a5b4a
--- /dev/null
+++ b/src/libgc/Makefile_insert
@@ -0,0 +1,13 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+libgc/all: libgc/libgc.a
+
+libgc/clean:
+ rm -f libgc/libgc.a $(libgc_libgc_a_OBJECTS)
+
+libgc_libgc_a_SOURCES = \
+ libgc/gc.cpp \
+ libgc/gc-alloc.h \
+ libgc/gc-core.h \
+ libgc/gc-managed.h \
+ libgc/gc-soft-ptr.h
diff --git a/src/libgc/gc-alloc.h b/src/libgc/gc-alloc.h
new file mode 100644
index 000000000..765b28b19
--- /dev/null
+++ b/src/libgc/gc-alloc.h
@@ -0,0 +1,90 @@
+/*
+ * Inkscape::GC::Alloc - GC-aware STL allocator
+ *
+ * Copyright 2004 MenTaLguY <mental@rydia.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * See the file COPYING for details.
+ *
+ */
+
+#ifndef SEEN_INKSCAPE_GC_ALLOC_H
+#define SEEN_INKSCAPE_GC_ALLOC_H
+
+#include <limits>
+#include <cstddef>
+#include "libgc/gc-core.h"
+
+namespace Inkscape {
+
+namespace GC {
+
+template <typename T, CollectionPolicy collect>
+class Alloc {
+public:
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T const *const_pointer;
+ typedef T &reference;
+ typedef T const &const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ template <typename U>
+ struct rebind { typedef Alloc<U, collect> other; };
+
+ Alloc() {}
+ template <typename U> Alloc(Alloc<U, collect> const &) {}
+
+ pointer address(reference r) { return &r; }
+ const_pointer address(const_reference r) { return &r; }
+
+ size_type max_size() const {
+ return std::numeric_limits<std::size_t>::max() / sizeof(T);
+ }
+
+ pointer allocate(size_type count, void const * =NULL) {
+ return static_cast<pointer>(::operator new(count * sizeof(T), SCANNED, collect));
+ }
+
+ void construct(pointer p, const_reference value) {
+ new (static_cast<void *>(p)) T(value);
+ }
+ void destroy(pointer p) { p->~T(); }
+
+ void deallocate(pointer p, size_type) { ::operator delete(p, GC); }
+};
+
+// allocators with the same collection policy are interchangable
+
+template <typename T1, typename T2,
+ CollectionPolicy collect1, CollectionPolicy collect2>
+bool operator==(Alloc<T1, collect1> const &, Alloc<T2, collect2> const &) {
+ return collect1 == collect2;
+}
+
+template <typename T1, typename T2,
+ CollectionPolicy collect1, CollectionPolicy collect2>
+bool operator!=(Alloc<T1, collect1> const &, Alloc<T2, collect2> const &) {
+ return collect1 != collect2;
+}
+
+}
+
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libgc/gc-core.h b/src/libgc/gc-core.h
new file mode 100644
index 000000000..d9d0bf4ff
--- /dev/null
+++ b/src/libgc/gc-core.h
@@ -0,0 +1,213 @@
+/** @file
+ * @brief Wrapper for Boehm GC
+ */
+/* Authors:
+ * MenTaLguY <mental@rydia.net>
+ *
+ * Copyright (C) 2004 MenTaLguY
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_GC_CORE_H
+#define SEEN_INKSCAPE_GC_CORE_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <new>
+#include <cstdlib>
+#include <cstddef>
+#ifdef HAVE_GC_GC_H
+# include <gc/gc.h>
+#else
+# include <gc.h>
+#endif
+
+namespace Inkscape {
+namespace GC {
+
+enum ScanPolicy {
+ SCANNED,
+ ATOMIC
+};
+
+enum CollectionPolicy {
+ AUTO,
+ MANUAL
+};
+
+enum Delete {
+ GC
+};
+
+typedef void (*CleanupFunc)(void *mem, void *data);
+
+struct Ops {
+ void (*do_init)();
+ void *(*malloc)(std::size_t size);
+ void *(*malloc_atomic)(std::size_t size);
+ void *(*malloc_uncollectable)(std::size_t size);
+ void *(*malloc_atomic_uncollectable)(std::size_t size);
+ void *(*base)(void *ptr);
+ void (*register_finalizer_ignore_self)(void *base,
+ CleanupFunc func, void *data,
+ CleanupFunc *old_func,
+ void **old_data);
+ int (*general_register_disappearing_link)(void **p_ptr,
+ void const *base);
+ int (*unregister_disappearing_link)(void **p_ptr);
+ std::size_t (*get_heap_size)();
+ std::size_t (*get_free_bytes)();
+ void (*gcollect)();
+ void (*enable)();
+ void (*disable)();
+ void (*free)(void *ptr);
+};
+
+struct Core {
+public:
+ static void init();
+ static inline void *malloc(std::size_t size) {
+ return _ops.malloc(size);
+ }
+ static inline void *malloc_atomic(std::size_t size) {
+ return _ops.malloc_atomic(size);
+ }
+ static inline void *malloc_uncollectable(std::size_t size) {
+ return _ops.malloc_uncollectable(size);
+ }
+ static inline void *malloc_atomic_uncollectable(std::size_t size) {
+ return _ops.malloc_atomic_uncollectable(size);
+ }
+ static inline void *base(void *ptr) {
+ return _ops.base(ptr);
+ }
+ static inline void register_finalizer_ignore_self(void *base,
+ CleanupFunc func,
+ void *data,
+ CleanupFunc *old_func,
+ void **old_data)
+ {
+ return _ops.register_finalizer_ignore_self(base, func, data,
+ old_func, old_data);
+ }
+ static inline int general_register_disappearing_link(void **p_ptr,
+ void *base)
+ {
+ return _ops.general_register_disappearing_link(p_ptr, base);
+ }
+ static inline int unregister_disappearing_link(void **p_ptr) {
+ return _ops.unregister_disappearing_link(p_ptr);
+ }
+ static inline std::size_t get_heap_size() {
+ return _ops.get_heap_size();
+ }
+ static inline std::size_t get_free_bytes() {
+ return _ops.get_free_bytes();
+ }
+ static inline void gcollect() {
+ _ops.gcollect();
+ }
+ static inline void enable() {
+ _ops.enable();
+ }
+ static inline void disable() {
+ _ops.disable();
+ }
+ static inline void free(void *ptr) {
+ return _ops.free(ptr);
+ }
+private:
+ static Ops _ops;
+};
+
+inline void init() {
+ Core::init();
+}
+
+void request_early_collection();
+
+}
+}
+
+inline void *operator new(std::size_t size,
+ Inkscape::GC::ScanPolicy scan,
+ Inkscape::GC::CollectionPolicy collect,
+ Inkscape::GC::CleanupFunc cleanup=NULL,
+ void *data=NULL)
+throw(std::bad_alloc)
+{
+ using namespace Inkscape::GC;
+
+ void *mem;
+ if ( collect == AUTO ) {
+ if ( scan == SCANNED ) {
+ mem = Core::malloc(size);
+ } else {
+ mem = Core::malloc_atomic(size);
+ }
+ } else {
+ if ( scan == SCANNED ) {
+ mem = Core::malloc_uncollectable(size);
+ } else {
+ mem = Core::malloc_atomic_uncollectable(size);
+ }
+ }
+ if (!mem) {
+ throw std::bad_alloc();
+ }
+ if (cleanup) {
+ Core::register_finalizer_ignore_self(mem, cleanup, data, NULL, NULL);
+ }
+ return mem;
+}
+
+inline void *operator new(std::size_t size,
+ Inkscape::GC::ScanPolicy scan,
+ Inkscape::GC::CleanupFunc cleanup=NULL,
+ void *data=NULL)
+throw(std::bad_alloc)
+{
+ return operator new(size, scan, Inkscape::GC::AUTO, cleanup, data);
+}
+
+inline void *operator new[](std::size_t size,
+ Inkscape::GC::ScanPolicy scan,
+ Inkscape::GC::CollectionPolicy collect,
+ Inkscape::GC::CleanupFunc cleanup=NULL,
+ void *data=NULL)
+throw(std::bad_alloc)
+{
+ return operator new(size, scan, collect, cleanup, data);
+}
+
+inline void *operator new[](std::size_t size,
+ Inkscape::GC::ScanPolicy scan,
+ Inkscape::GC::CleanupFunc cleanup=NULL,
+ void *data=NULL)
+throw(std::bad_alloc)
+{
+ return operator new[](size, scan, Inkscape::GC::AUTO, cleanup, data);
+}
+
+inline void operator delete(void *mem, Inkscape::GC::Delete) {
+ Inkscape::GC::Core::free(mem);
+}
+
+inline void operator delete[](void *mem, Inkscape::GC::Delete) {
+ operator delete(mem, Inkscape::GC::GC);
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libgc/gc-managed.h b/src/libgc/gc-managed.h
new file mode 100644
index 000000000..9f6d9c2f6
--- /dev/null
+++ b/src/libgc/gc-managed.h
@@ -0,0 +1,63 @@
+/** @file
+ * @brief Base class for GC-managed objects
+ */
+/* Copyright 2004 MenTaLguY <mental@rydia.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * See the file COPYING for details.
+ */
+
+#ifndef SEEN_INKSCAPE_GC_MANAGED_H
+#define SEEN_INKSCAPE_GC_MANAGED_H
+
+#include "libgc/gc-core.h"
+
+namespace Inkscape {
+
+namespace GC {
+
+/** @brief A base class for objects for whom the normal new and delete
+ * operators should use the garbage-collected allocator
+ */
+template <ScanPolicy default_scan=SCANNED,
+ CollectionPolicy default_collect=AUTO>
+class Managed {
+public:
+ void *operator new(std::size_t size,
+ ScanPolicy scan=default_scan,
+ CollectionPolicy collect=default_collect)
+ throw (std::bad_alloc)
+ {
+ return ::operator new(size, scan, collect);
+ }
+
+ void *operator new[](std::size_t size,
+ ScanPolicy scan=default_scan,
+ CollectionPolicy collect=default_collect)
+ throw (std::bad_alloc)
+ {
+ return ::operator new[](size, scan, collect);
+ }
+
+ void operator delete(void *p) { return ::operator delete(p, GC); }
+};
+
+}
+
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libgc/gc-soft-ptr.h b/src/libgc/gc-soft-ptr.h
new file mode 100644
index 000000000..bb26ebb04
--- /dev/null
+++ b/src/libgc/gc-soft-ptr.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 MenTaLguY <mental@rydia.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * See the file COPYING for details.
+ *
+ */
+
+#ifndef SEEN_INKSCAPE_GC_SOFT_PTR_H
+#define SEEN_INKSCAPE_GC_SOFT_PTR_H
+
+#include "libgc/gc-core.h"
+
+namespace Inkscape {
+
+namespace GC {
+
+/**
+ * A class for pointers which can be automatically cleared to break
+ * finalization cycles.
+ */
+template <typename T>
+class soft_ptr {
+public:
+ soft_ptr(T *pointer=NULL) : _pointer(pointer) {
+ _register();
+ }
+
+ operator T *() const { return static_cast<T *>(_pointer); }
+ T &operator*() const { return *static_cast<T *>(_pointer); }
+ T *operator->() const { return static_cast<T *>(_pointer); }
+ T &operator[](int i) const { return static_cast<T *>(_pointer)[i]; }
+
+ soft_ptr &operator=(T *pointer) {
+ _pointer = pointer;
+ return *this;
+ }
+
+ // default copy
+
+private:
+ void _register() {
+ void *base=Core::base(this);
+ if (base) {
+ Core::general_register_disappearing_link(&_pointer, base);
+ }
+ }
+
+ void *_pointer;
+};
+
+}
+
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libgc/gc.cpp b/src/libgc/gc.cpp
new file mode 100644
index 000000000..044fc6065
--- /dev/null
+++ b/src/libgc/gc.cpp
@@ -0,0 +1,312 @@
+/** @file
+ * Wrapper for Boehm GC.
+ */
+/* Authors:
+ * MenTaLguY <mental@rydia.net>
+ *
+ * Copyright (C) 2004 MenTaLguY
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "libgc/gc-core.h"
+#include <stdexcept>
+#include <cstring>
+#include <string>
+#include <glib.h>
+#include <sigc++/functors/ptr_fun.h>
+#include <glibmm/main.h>
+#include <cstddef>
+
+namespace Inkscape {
+namespace GC {
+
+namespace {
+
+void display_warning(char *msg, GC_word arg) {
+ g_warning(msg, arg);
+}
+
+void do_init() {
+ GC_no_dls = 1;
+ GC_all_interior_pointers = 1;
+ GC_finalize_on_demand = 0;
+
+ GC_INIT();
+
+ GC_set_warn_proc(&display_warning);
+}
+
+void *debug_malloc(std::size_t size) {
+ return GC_debug_malloc(size, GC_EXTRAS);
+}
+
+void *debug_malloc_atomic(std::size_t size) {
+ return GC_debug_malloc_atomic(size, GC_EXTRAS);
+}
+
+void *debug_malloc_uncollectable(std::size_t size) {
+ return GC_debug_malloc_uncollectable(size, GC_EXTRAS);
+}
+
+void *debug_malloc_atomic_uncollectable(std::size_t size) {
+ return GC_debug_malloc_uncollectable(size, GC_EXTRAS);
+}
+
+std::ptrdiff_t compute_debug_base_fixup() {
+ char *base=reinterpret_cast<char *>(GC_debug_malloc(1, GC_EXTRAS));
+ char *real_base=reinterpret_cast<char *>(GC_base(base));
+ GC_debug_free(base);
+ return base - real_base;
+}
+
+inline std::ptrdiff_t const &debug_base_fixup() {
+ static std::ptrdiff_t fixup=compute_debug_base_fixup();
+ return fixup;
+}
+
+void *debug_base(void *ptr) {
+ char *base=reinterpret_cast<char *>(GC_base(ptr));
+ return base + debug_base_fixup();
+}
+
+int debug_general_register_disappearing_link(void **p_ptr, void const *base) {
+ char const *real_base = reinterpret_cast<char const *>(base) - debug_base_fixup();
+#if (GC_MAJOR_VERSION >= 7 && GC_MINOR_VERSION >= 4)
+ return GC_general_register_disappearing_link(p_ptr, real_base);
+#else // compatibility with older Boehm GC versions
+ return GC_general_register_disappearing_link(p_ptr, const_cast<char *>(real_base));
+#endif
+}
+
+void dummy_do_init() {}
+
+void *dummy_base(void *) { return NULL; }
+
+void dummy_register_finalizer(void *, CleanupFunc, void *,
+ CleanupFunc *old_func, void **old_data)
+{
+ if (old_func) {
+ *old_func = NULL;
+ }
+ if (old_data) {
+ *old_data = NULL;
+ }
+}
+
+int dummy_general_register_disappearing_link(void **, void const *) { return false; }
+
+int dummy_unregister_disappearing_link(void **/*link*/) { return false; }
+
+std::size_t dummy_get_heap_size() { return 0; }
+
+std::size_t dummy_get_free_bytes() { return 0; }
+
+void dummy_gcollect() {}
+
+void dummy_enable() {}
+
+void dummy_disable() {}
+
+Ops enabled_ops = {
+ &do_init,
+ &GC_malloc,
+ &GC_malloc_atomic,
+ &GC_malloc_uncollectable,
+ &GC_malloc_atomic_uncollectable,
+ &GC_base,
+ &GC_register_finalizer_ignore_self,
+#if (GC_MAJOR_VERSION >= 7 && GC_MINOR_VERSION >= 4)
+ &GC_general_register_disappearing_link,
+#else // compatibility with older Boehm GC versions
+ (int (*)(void**, const void*))(&GC_general_register_disappearing_link),
+#endif
+ &GC_unregister_disappearing_link,
+ &GC_get_heap_size,
+ &GC_get_free_bytes,
+ &GC_gcollect,
+ &GC_enable,
+ &GC_disable,
+ &GC_free
+};
+
+Ops debug_ops = {
+ &do_init,
+ &debug_malloc,
+ &debug_malloc_atomic,
+ &debug_malloc_uncollectable,
+ &debug_malloc_atomic_uncollectable,
+ &debug_base,
+ &GC_debug_register_finalizer_ignore_self,
+ &debug_general_register_disappearing_link,
+ &GC_unregister_disappearing_link,
+ &GC_get_heap_size,
+ &GC_get_free_bytes,
+ &GC_gcollect,
+ &GC_enable,
+ &GC_disable,
+ &GC_debug_free
+};
+
+Ops disabled_ops = {
+ &dummy_do_init,
+ &std::malloc,
+ &std::malloc,
+ &std::malloc,
+ &std::malloc,
+ &dummy_base,
+ &dummy_register_finalizer,
+ &dummy_general_register_disappearing_link,
+ &dummy_unregister_disappearing_link,
+ &dummy_get_heap_size,
+ &dummy_get_free_bytes,
+ &dummy_gcollect,
+ &dummy_enable,
+ &dummy_disable,
+ &std::free
+};
+
+class InvalidGCModeError : public std::runtime_error {
+public:
+ InvalidGCModeError(const char *mode)
+ : runtime_error(std::string("Unknown GC mode \"") + mode + "\"")
+ {}
+};
+
+Ops const &get_ops() throw (InvalidGCModeError) {
+ char *mode_string=std::getenv("_INKSCAPE_GC");
+ if (mode_string) {
+ if (!std::strcmp(mode_string, "enable")) {
+ return enabled_ops;
+ } else if (!std::strcmp(mode_string, "debug")) {
+ return debug_ops;
+ } else if (!std::strcmp(mode_string, "disable")) {
+ return disabled_ops;
+ } else {
+ throw InvalidGCModeError(mode_string);
+ }
+ } else {
+ return enabled_ops;
+ }
+}
+
+void die_because_not_initialized() {
+ g_error("Attempt to use GC allocator before call to Inkscape::GC::init()");
+}
+
+void *stub_malloc(std::size_t) {
+ die_because_not_initialized();
+ return NULL;
+}
+
+void *stub_base(void *) {
+ die_because_not_initialized();
+ return NULL;
+}
+
+void stub_register_finalizer_ignore_self(void *, CleanupFunc, void *,
+ CleanupFunc *, void **)
+{
+ die_because_not_initialized();
+}
+
+int stub_general_register_disappearing_link(void **, void const *) {
+ die_because_not_initialized();
+ return 0;
+}
+
+int stub_unregister_disappearing_link(void **) {
+ die_because_not_initialized();
+ return 0;
+}
+
+std::size_t stub_get_heap_size() {
+ die_because_not_initialized();
+ return 0;
+}
+
+std::size_t stub_get_free_bytes() {
+ die_because_not_initialized();
+ return 0;
+}
+
+void stub_gcollect() {
+ die_because_not_initialized();
+}
+
+void stub_enable() {
+ die_because_not_initialized();
+}
+
+void stub_disable() {
+ die_because_not_initialized();
+}
+
+void stub_free(void *) {
+ die_because_not_initialized();
+}
+
+}
+
+Ops Core::_ops = {
+ NULL,
+ &stub_malloc,
+ &stub_malloc,
+ &stub_malloc,
+ &stub_malloc,
+ &stub_base,
+ &stub_register_finalizer_ignore_self,
+ &stub_general_register_disappearing_link,
+ &stub_unregister_disappearing_link,
+ &stub_get_heap_size,
+ &stub_get_free_bytes,
+ &stub_gcollect,
+ &stub_enable,
+ &stub_disable,
+ &stub_free
+};
+
+void Core::init() {
+ try {
+ _ops = get_ops();
+ } catch (InvalidGCModeError &e) {
+ g_warning("%s; enabling normal collection", e.what());
+ _ops = enabled_ops;
+ }
+
+ _ops.do_init();
+}
+
+
+namespace {
+
+bool collection_requested=false;
+bool collection_task() {
+ Core::gcollect();
+ Core::gcollect();
+ collection_requested=false;
+ return false;
+}
+
+}
+
+void request_early_collection() {
+ if (!collection_requested) {
+ collection_requested=true;
+ Glib::signal_idle().connect(sigc::ptr_fun(&collection_task));
+ }
+}
+
+}
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :