1 /** \file
2 * Inkscape::GC::Anchored - base class for anchored GC-managed objects
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_ANCHORED_H
13 #define SEEN_INKSCAPE_GC_ANCHORED_H
15 #include <glib/gmessages.h>
16 #include "gc-managed.h"
18 namespace Inkscape {
20 namespace GC {
22 /**
23 * A base class for anchored objects.
24 *
25 * Objects are managed by our mark-and-sweep collector, but are anchored
26 * against garbage collection so long as their reference count is nonzero.
27 *
28 * Object and member destructors will not be called on destruction
29 * unless a subclass also inherits from Inkscape::GC::Finalized.
30 *
31 * New instances of anchored objects should be created using the C++ new
32 * operator. Under normal circumstances they should not be created on
33 * the stack.
34 *
35 * A newly created anchored object begins with a refcount of one, and
36 * will not be collected unless the refcount is zero.
37 *
38 * NOTE: If you create an object yourself, it is already anchored for
39 * you. You do not need to anchor it a second time.
40 *
41 * Note that a cycle involving an anchored object (with nonzero refcount)
42 * cannot be collected. To avoid this, don't increment refcounts for
43 * pointers between two GC-managed objects.
44 *
45 * @see Inkscape::GC::Managed
46 * @see Inkscape::GC::Finalized
47 * @see Inkscape::GC::anchor
48 * @see Inkscape::GC::release
49 */
51 class Anchored {
52 public:
53 void anchor() const {
54 if (!_anchor) {
55 _anchor = _new_anchor();
56 }
57 _anchor->refcount++;
58 }
60 void release() const {
61 if (!--_anchor->refcount) {
62 _free_anchor(_anchor);
63 _anchor = NULL;
64 }
65 }
67 protected:
68 Anchored() : _anchor(NULL) { anchor(); } // initial refcount of one
70 private:
71 struct Anchor : public Managed<SCANNED, MANUAL> {
72 Anchor() : refcount(0) {}
73 Anchor(Anchored const *obj) : refcount(0) {
74 base = Core::base(const_cast<Anchored *>(obj));
75 }
76 int refcount;
77 void *base;
78 };
80 mutable Anchor *_anchor;
82 Anchor *_new_anchor() const;
83 void _free_anchor(Anchor *anchor) const;
85 Anchored(Anchored const &); // no copy
86 void operator=(Anchored const &); // no assign
87 };
89 /**
90 * @brief Increments the reference count of a anchored object.
91 *
92 * This function template generates functions which take
93 * a reference to a anchored object of a given type, increment
94 * that object's reference count, and return a reference to the
95 * object of the same type as the function's parameter.
96 *
97 * @param m a reference to a anchored object
98 *
99 * @return the reference to the object
100 */
101 template <typename R>
102 static R &anchor(R &r) {
103 static_cast<Anchored const &>(const_cast<R const &>(r)).anchor();
104 return r;
105 }
107 /**
108 * @brief Increments the reference count of a anchored object.
109 *
110 * This function template generates functions which take
111 * a pointer to a anchored object of a given type, increment
112 * that object's reference count, and return a pointer to the
113 * object of the same type as the function's parameter.
114 *
115 * @param m a pointer to anchored object
116 *
117 * @return the pointer to the object
118 */
119 template <typename R>
120 static R *anchor(R *r) {
121 static_cast<Anchored const *>(const_cast<R const *>(r))->anchor();
122 return r;
123 }
125 /**
126 * @brief Decrements the reference count of a anchored object.
127 *
128 * This function template generates functions which take
129 * a reference to a anchored object of a given type, increment
130 * that object's reference count, and return a reference to the
131 * object of the same type as the function's parameter.
132 *
133 * The return value is safe to use since the object, even if
134 * its refcount has reached zero, will not actually be collected
135 * until there are no references to it in local variables or
136 * parameters.
137 *
138 * @param m a reference to a anchored object
139 *
140 * @return the reference to the object
141 */
142 template <typename R>
143 static R &release(R &r) {
144 static_cast<Anchored const &>(const_cast<R const &>(r)).release();
145 return r;
146 }
148 /**
149 * @brief Decrements the reference count of a anchored object.
150 *
151 * This function template generates functions which take
152 * a pointer to a anchored object of a given type, increment
153 * that object's reference count, and return a pointer to the
154 * object of the same type as the function's parameter.
155 *
156 * The return value is safe to use since the object, even if
157 * its refcount has reached zero, will not actually be collected
158 * until there are no references to it in local variables or
159 * parameters.
160 *
161 * @param m a pointer to a anchored object
162 *
163 * @return the pointer to the object
164 */
165 template <typename R>
166 static R *release(R *r) {
167 static_cast<Anchored const *>(const_cast<R const *>(r))->release();
168 return r;
169 }
171 }
173 }
175 #endif
176 /*
177 Local Variables:
178 mode:c++
179 c-file-style:"stroustrup"
180 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
181 indent-tabs-mode:nil
182 fill-column:99
183 End:
184 */
185 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :