Skip to content

Commit 8dae7b4

Browse files
authoredJan 24, 2021
Improve irr_ptr (#10808)
1 parent ad9adcb commit 8dae7b4

File tree

1 file changed

+76
-13
lines changed

1 file changed

+76
-13
lines changed
 

‎src/irr_ptr.h

+76-13
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2727
* It should only be used for user-managed objects, i.e. those created with
2828
* the @c new operator or @c create* functions, like:
2929
* `irr_ptr<scene::IMeshBuffer> buf{new scene::SMeshBuffer()};`
30+
* The reference counting is *not* balanced as new objects have reference
31+
* count set to one, and the @c irr_ptr constructor (and @c reset) assumes
32+
* ownership of that reference.
3033
*
31-
* It should *never* be used for engine-managed objects, including
32-
* those created with @c addTexture and similar methods.
34+
* It shouldn’t be used for engine-managed objects, including those created
35+
* with @c addTexture and similar methods. Constructing @c irr_ptr directly
36+
* from such object is a bug and may lead to a crash. Indirect construction
37+
* is possible though; see the @c grab free function for details and use cases.
3338
*/
3439
template <class ReferenceCounted,
3540
class = typename std::enable_if<std::is_base_of<IReferenceCounted,
@@ -38,16 +43,6 @@ class irr_ptr
3843
{
3944
ReferenceCounted *value = nullptr;
4045

41-
/** Drops stored pointer replacing it with the given one.
42-
* @note Copy semantics: reference counter *is* increased.
43-
*/
44-
void grab(ReferenceCounted *object)
45-
{
46-
if (object)
47-
object->grab();
48-
reset(object);
49-
}
50-
5146
public:
5247
irr_ptr() {}
5348

@@ -71,8 +66,10 @@ class irr_ptr
7166
reset(b.release());
7267
}
7368

74-
/** Constructs a shared pointer out of a plain one
69+
/** Constructs a shared pointer out of a plain one to control object lifetime.
70+
* @param object The object, usually returned by some @c create* function.
7571
* @note Move semantics: reference counter is *not* increased.
72+
* @warning Never wrap any @c add* function with this!
7673
*/
7774
explicit irr_ptr(ReferenceCounted *object) noexcept { reset(object); }
7875

@@ -134,4 +131,70 @@ class irr_ptr
134131
value->drop();
135132
value = object;
136133
}
134+
135+
/** Drops stored pointer replacing it with the given one.
136+
* @note Copy semantics: reference counter *is* increased.
137+
*/
138+
void grab(ReferenceCounted *object) noexcept
139+
{
140+
if (object)
141+
object->grab();
142+
reset(object);
143+
}
137144
};
145+
146+
// clang-format off
147+
// ^ dislikes long lines
148+
149+
/** Constructs a shared pointer as a *secondary* reference to an object
150+
*
151+
* This function is intended to make a temporary reference to an object which
152+
* is owned elsewhere so that it is not destroyed too early. To acheive that
153+
* it does balanced reference counting, i.e. reference count is increased
154+
* in this function and decreased when the returned pointer is destroyed.
155+
*/
156+
template <class ReferenceCounted>
157+
irr_ptr<ReferenceCounted> grab(ReferenceCounted *object) noexcept
158+
{
159+
irr_ptr<ReferenceCounted> ptr;
160+
ptr.grab(object);
161+
return ptr;
162+
}
163+
164+
template <typename ReferenceCounted>
165+
bool operator==(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
166+
{
167+
return a.get() == b.get();
168+
}
169+
170+
template <typename ReferenceCounted>
171+
bool operator==(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
172+
{
173+
return a.get() == b;
174+
}
175+
176+
template <typename ReferenceCounted>
177+
bool operator==(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept
178+
{
179+
return a == b.get();
180+
}
181+
182+
template <typename ReferenceCounted>
183+
bool operator!=(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
184+
{
185+
return a.get() != b.get();
186+
}
187+
188+
template <typename ReferenceCounted>
189+
bool operator!=(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
190+
{
191+
return a.get() != b;
192+
}
193+
194+
template <typename ReferenceCounted>
195+
bool operator!=(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept
196+
{
197+
return a != b.get();
198+
}
199+
200+
// clang-format on

0 commit comments

Comments
 (0)
Please sign in to comment.