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