Improve irr_ptr (#10808)

This commit is contained in:
Vitaliy 2021-01-24 17:40:34 +03:00 committed by GitHub
parent ad9adcb884
commit 8dae7b47fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -27,9 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
* It should only be used for user-managed objects, i.e. those created with * It should only be used for user-managed objects, i.e. those created with
* the @c new operator or @c create* functions, like: * the @c new operator or @c create* functions, like:
* `irr_ptr<scene::IMeshBuffer> buf{new scene::SMeshBuffer()};` * `irr_ptr<scene::IMeshBuffer> buf{new scene::SMeshBuffer()};`
* The reference counting is *not* balanced as new objects have reference
* count set to one, and the @c irr_ptr constructor (and @c reset) assumes
* ownership of that reference.
* *
* It should *never* be used for engine-managed objects, including * It shouldnt be used for engine-managed objects, including those created
* those created with @c addTexture and similar methods. * with @c addTexture and similar methods. Constructing @c irr_ptr directly
* from such object is a bug and may lead to a crash. Indirect construction
* is possible though; see the @c grab free function for details and use cases.
*/ */
template <class ReferenceCounted, template <class ReferenceCounted,
class = typename std::enable_if<std::is_base_of<IReferenceCounted, class = typename std::enable_if<std::is_base_of<IReferenceCounted,
@ -38,16 +43,6 @@ class irr_ptr
{ {
ReferenceCounted *value = nullptr; ReferenceCounted *value = nullptr;
/** Drops stored pointer replacing it with the given one.
* @note Copy semantics: reference counter *is* increased.
*/
void grab(ReferenceCounted *object)
{
if (object)
object->grab();
reset(object);
}
public: public:
irr_ptr() {} irr_ptr() {}
@ -71,8 +66,10 @@ public:
reset(b.release()); reset(b.release());
} }
/** Constructs a shared pointer out of a plain one /** Constructs a shared pointer out of a plain one to control object lifetime.
* @param object The object, usually returned by some @c create* function.
* @note Move semantics: reference counter is *not* increased. * @note Move semantics: reference counter is *not* increased.
* @warning Never wrap any @c add* function with this!
*/ */
explicit irr_ptr(ReferenceCounted *object) noexcept { reset(object); } explicit irr_ptr(ReferenceCounted *object) noexcept { reset(object); }
@ -134,4 +131,70 @@ public:
value->drop(); value->drop();
value = object; value = object;
} }
/** Drops stored pointer replacing it with the given one.
* @note Copy semantics: reference counter *is* increased.
*/
void grab(ReferenceCounted *object) noexcept
{
if (object)
object->grab();
reset(object);
}
}; };
// clang-format off
// ^ dislikes long lines
/** Constructs a shared pointer as a *secondary* reference to an object
*
* This function is intended to make a temporary reference to an object which
* is owned elsewhere so that it is not destroyed too early. To acheive that
* it does balanced reference counting, i.e. reference count is increased
* in this function and decreased when the returned pointer is destroyed.
*/
template <class ReferenceCounted>
irr_ptr<ReferenceCounted> grab(ReferenceCounted *object) noexcept
{
irr_ptr<ReferenceCounted> ptr;
ptr.grab(object);
return ptr;
}
template <typename ReferenceCounted>
bool operator==(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
{
return a.get() == b.get();
}
template <typename ReferenceCounted>
bool operator==(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
{
return a.get() == b;
}
template <typename ReferenceCounted>
bool operator==(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept
{
return a == b.get();
}
template <typename ReferenceCounted>
bool operator!=(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
{
return a.get() != b.get();
}
template <typename ReferenceCounted>
bool operator!=(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
{
return a.get() != b;
}
template <typename ReferenceCounted>
bool operator!=(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept
{
return a != b.get();
}
// clang-format on