forked from boostorg/beast
Refactor SharedPtr and fix ContainerDeletePolicy bug
This commit is contained in:
1 parent
aa2773e483
commit
201221253d
21 files changed
+544
-457
No files matched your search
@@ -0,0 +1,192 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SHAREDOBJECT_H_INCLUDED
|
||||
#define BEAST_SHAREDOBJECT_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Adds reference-counting to an object.
|
||||
|
||||
To add reference-counting to a class, derive it from this class, and
|
||||
use the SharedPtr class to point to it.
|
||||
|
||||
e.g. @code
|
||||
class MyClass : public SharedObject
|
||||
{
|
||||
void foo();
|
||||
|
||||
// This is a neat way of declaring a typedef for a pointer class,
|
||||
// rather than typing out the full templated name each time..
|
||||
typedef SharedPtr<MyClass> Ptr;
|
||||
};
|
||||
|
||||
MyClass::Ptr p = new MyClass();
|
||||
MyClass::Ptr p2 = p;
|
||||
p = nullptr;
|
||||
p2->foo();
|
||||
@endcode
|
||||
|
||||
Once a new SharedObject has been assigned to a pointer, be
|
||||
careful not to delete the object manually.
|
||||
|
||||
This class uses an Atomic<int> value to hold the reference count, so that it
|
||||
the pointers can be passed between threads safely. For a faster but non-thread-safe
|
||||
version, use SingleThreadedSharedObject instead.
|
||||
|
||||
@see SharedPtr, SharedObjectArray, SingleThreadedSharedObject
|
||||
*/
|
||||
class BEAST_API SharedObject : public Uncopyable
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Increments the object's reference count.
|
||||
|
||||
This is done automatically by the smart pointer, but is public just
|
||||
in case it's needed for nefarious purposes.
|
||||
*/
|
||||
inline void incReferenceCount() noexcept
|
||||
{
|
||||
++refCount;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
|
||||
If doDelete is true the object will be deleted when the reference
|
||||
count drops to zero. The delete is performed using the regular
|
||||
operator and does NOT go through the ContainerDeletePolicy.
|
||||
|
||||
The return value indicates if the reference count dropped to zero,
|
||||
so callers who know the derived type can use the ContainerDeletePolicy.
|
||||
*/
|
||||
inline bool decReferenceCount (bool doDelete = true) noexcept
|
||||
{
|
||||
bassert (getReferenceCount() > 0);
|
||||
if (--refCount == 0)
|
||||
{
|
||||
if (doDelete)
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns the object's current reference count. */
|
||||
inline int getReferenceCount() const noexcept { return refCount.get(); }
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates the reference-counted object (with an initial ref count of zero). */
|
||||
SharedObject()
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~SharedObject()
|
||||
{
|
||||
// it's dangerous to delete an object that's still referenced by something else!
|
||||
bassert (getReferenceCount() == 0);
|
||||
}
|
||||
|
||||
/** Resets the reference count to zero without deleting the object.
|
||||
You should probably never need to use this!
|
||||
*/
|
||||
void resetReferenceCount() noexcept
|
||||
{
|
||||
refCount = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Atomic <int> refCount;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Adds reference-counting to an object.
|
||||
|
||||
This is effectively a version of the SharedObject class, but which
|
||||
uses a non-atomic counter, and so is not thread-safe (but which will be more
|
||||
efficient).
|
||||
For more details on how to use it, see the SharedObject class notes.
|
||||
|
||||
@see SharedObject, SharedPtr, SharedObjectArray
|
||||
*/
|
||||
class BEAST_API SingleThreadedSharedObject : public Uncopyable
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Increments the object's reference count.
|
||||
|
||||
This is done automatically by the smart pointer, but is public just
|
||||
in case it's needed for nefarious purposes.
|
||||
*/
|
||||
inline void incReferenceCount() noexcept
|
||||
{
|
||||
++refCount;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
|
||||
If doDelete is true the object will be deleted when the reference
|
||||
count drops to zero. The delete is performed using the regular
|
||||
operator and does NOT go through the ContainerDeletePolicy.
|
||||
|
||||
The return value indicates if the reference count dropped to zero,
|
||||
so callers who know the derived type can use the ContainerDeletePolicy.
|
||||
*/
|
||||
inline bool decReferenceCount (bool doDelete = true) noexcept
|
||||
{
|
||||
bassert (getReferenceCount() > 0);
|
||||
if (--refCount == 0)
|
||||
{
|
||||
if (doDelete)
|
||||
delete this;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns the object's current reference count. */
|
||||
inline int getReferenceCount() const noexcept { return refCount; }
|
||||
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates the reference-counted object (with an initial ref count of zero). */
|
||||
SingleThreadedSharedObject() : refCount (0) {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~SingleThreadedSharedObject()
|
||||
{
|
||||
// it's dangerous to delete an object that's still referenced by something else!
|
||||
bassert (getReferenceCount() == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
int refCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,309 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CORE_SHAREDPTR_H_INCLUDED
|
||||
#define BEAST_CORE_SHAREDPTR_H_INCLUDED
|
||||
|
||||
// Visual Studio doesn't seem to do very well when it comes
|
||||
// to templated constructors and assignments so we provide
|
||||
// non-templated versions when U and T are the same type.
|
||||
//
|
||||
#ifndef BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||
#define BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS 1
|
||||
#endif
|
||||
|
||||
/** A smart-pointer container.
|
||||
|
||||
Requirement:
|
||||
T must support the SharedObject concept.
|
||||
|
||||
The template parameter specifies the class of the object you want to point
|
||||
to - the easiest way to make a class reference-countable is to simply make
|
||||
it inherit from SharedObject, but if you need to, you could roll your own
|
||||
reference-countable class by implementing a pair of methods called
|
||||
incReferenceCount() and decReferenceCount().
|
||||
|
||||
When using this class, you'll probably want to create a typedef to
|
||||
abbreviate the full templated name - e.g.
|
||||
|
||||
@code
|
||||
|
||||
typedef SharedPtr <MyClass> MyClassPtr;
|
||||
|
||||
@endcode
|
||||
|
||||
@see SharedObject, SharedObjectArray
|
||||
*/
|
||||
template <class T>
|
||||
class SharedPtr
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
/** The class being referenced by this container. */
|
||||
typedef T ReferencedType;
|
||||
|
||||
/** Construct a container pointing to nothing. */
|
||||
SharedPtr () noexcept
|
||||
: m_p (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Construct a container holding an object.
|
||||
This will increment the object's reference-count if it is non-null.
|
||||
Requirement:
|
||||
U* must be convertible to T*
|
||||
*/
|
||||
/// @{
|
||||
SharedPtr (T* t) noexcept
|
||||
: m_p (acquire (t))
|
||||
{
|
||||
}
|
||||
|
||||
template <class U>
|
||||
SharedPtr (U* u) noexcept
|
||||
: m_p (acquire (u))
|
||||
{
|
||||
}
|
||||
/// @}
|
||||
|
||||
/** Construct a container holding an object from another container.
|
||||
This will increment the object's reference-count (if it is non-null).
|
||||
Requirement:
|
||||
U* must be convertible to T*
|
||||
*/
|
||||
/// @{
|
||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||
SharedPtr (SharedPtr const& sp) noexcept
|
||||
: m_p (acquire (sp.get ()))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class U>
|
||||
SharedPtr (SharedPtr <U> const& sp) noexcept
|
||||
: m_p (acquire (sp.get ()))
|
||||
{
|
||||
}
|
||||
/// @}
|
||||
|
||||
/** Assign a different object to the container.
|
||||
The previous object beind held, if any, loses a reference count and
|
||||
will be destroyed if it is the last reference.
|
||||
Requirement:
|
||||
U* must be convertible to T*
|
||||
*/
|
||||
/// @{
|
||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||
SharedPtr& operator= (T* t)
|
||||
{
|
||||
return assign (t);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class U>
|
||||
SharedPtr& operator= (U* u)
|
||||
{
|
||||
return assign (u);
|
||||
}
|
||||
/// @}
|
||||
|
||||
/** Assign an object from another container to this one. */
|
||||
/// @{
|
||||
SharedPtr& operator= (SharedPtr const& sp)
|
||||
{
|
||||
return assign (sp.get ());
|
||||
}
|
||||
|
||||
/** Assign an object from another container to this one. */
|
||||
template <class U>
|
||||
SharedPtr& operator= (SharedPtr <U> const& sp)
|
||||
{
|
||||
return assign (sp.get ());
|
||||
}
|
||||
/// @}
|
||||
|
||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
/** Construct a container with an object transferred from another container.
|
||||
The originating container loses its reference to the object.
|
||||
Requires:
|
||||
U* must be convertible to T*
|
||||
*/
|
||||
/// @{
|
||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||
SharedPtr (SharedPtr && sp) noexcept
|
||||
: m_p (sp.swap <T> (nullptr))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class U>
|
||||
SharedPtr (SharedPtr <U>&& sp) noexcept
|
||||
: m_p (sp.swap <U> (nullptr))
|
||||
{
|
||||
}
|
||||
/// @}
|
||||
|
||||
/** Transfer ownership of another object to this container.
|
||||
The originating container loses its reference to the object.
|
||||
Requires:
|
||||
U* must be convertible to T*
|
||||
*/
|
||||
/// @{
|
||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||
SharedPtr& operator= (SharedPtr && sp)
|
||||
{
|
||||
return assign (sp.swap <T> (nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class U>
|
||||
SharedPtr& operator= (SharedPtr <U>&& sp)
|
||||
{
|
||||
return assign (sp.swap <U> (nullptr));
|
||||
}
|
||||
/// @}
|
||||
#endif
|
||||
|
||||
/** Destroy the container and release the held reference, if any.
|
||||
*/
|
||||
~SharedPtr ()
|
||||
{
|
||||
if (m_p != nullptr)
|
||||
if (m_p->decReferenceCount (false))
|
||||
ContainerDeletePolicy <T>::destroy (m_p);
|
||||
}
|
||||
|
||||
/** Returns `true` if the container is not pointing to an object. */
|
||||
bool empty () const noexcept
|
||||
{
|
||||
return m_p == nullptr;
|
||||
}
|
||||
|
||||
/** Returns the object that this pointer references if any, else nullptr. */
|
||||
operator T* () const noexcept
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
/** Returns the object that this pointer references if any, else nullptr. */
|
||||
T* operator-> () const noexcept
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
/** Returns the object that this pointer references if any, else nullptr. */
|
||||
T* get () const noexcept
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
/** Returns the object that this pointer references if any, else nullptr.
|
||||
DEPRECATED
|
||||
*/
|
||||
T* getObject () const noexcept
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
||||
private:
|
||||
// Acquire a reference to u for the caller.
|
||||
//
|
||||
template <class U>
|
||||
static T* acquire (U* u) noexcept
|
||||
{
|
||||
if (u != nullptr)
|
||||
u->incReferenceCount ();
|
||||
return u;
|
||||
}
|
||||
|
||||
// Swap ownership of the currently referenced object.
|
||||
// The caller receives a pointer to the original object,
|
||||
// and this container is left with the passed object. No
|
||||
// reference counts are changed.
|
||||
//
|
||||
template <class U>
|
||||
T* swap (U* u)
|
||||
{
|
||||
T* const t (m_p);
|
||||
m_p = u;
|
||||
return t;
|
||||
}
|
||||
|
||||
// Acquire ownership of u.
|
||||
// Any previous reference is released.
|
||||
//
|
||||
template <class U>
|
||||
SharedPtr& assign (U* u)
|
||||
{
|
||||
if (m_p != u)
|
||||
SharedPtr <T> old (
|
||||
this->swap (acquire (u)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* m_p;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// SharedPtr comparisons.
|
||||
/// @{
|
||||
template <class T, class U>
|
||||
bool operator== (SharedPtr <T> const& lhs, U* const rhs) noexcept
|
||||
{
|
||||
return lhs.get() == rhs;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator== (SharedPtr <T> const& lhs, SharedPtr <U> const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator== (T const* lhs, SharedPtr<T> const& rhs) noexcept
|
||||
{
|
||||
return lhs == rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!= (SharedPtr <T> const& lhs, T const* rhs) noexcept
|
||||
{
|
||||
return lhs.get() != rhs;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!= (SharedPtr <T> const& lhs, SharedPtr <T> const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() != rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!= (T const* lhs, SharedPtr<T> const& rhs) noexcept
|
||||
{
|
||||
return lhs != rhs.get();
|
||||
}
|
||||
/// @}
|
||||
|
||||
#endif
|
||||
@@ -1,411 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SHAREDOBJECT_H_INCLUDED
|
||||
#define BEAST_SHAREDOBJECT_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Adds reference-counting to an object.
|
||||
|
||||
To add reference-counting to a class, derive it from this class, and
|
||||
use the SharedObjectPtr class to point to it.
|
||||
|
||||
e.g. @code
|
||||
class MyClass : public SharedObject
|
||||
{
|
||||
void foo();
|
||||
|
||||
// This is a neat way of declaring a typedef for a pointer class,
|
||||
// rather than typing out the full templated name each time..
|
||||
typedef SharedObjectPtr<MyClass> Ptr;
|
||||
};
|
||||
|
||||
MyClass::Ptr p = new MyClass();
|
||||
MyClass::Ptr p2 = p;
|
||||
p = nullptr;
|
||||
p2->foo();
|
||||
@endcode
|
||||
|
||||
Once a new SharedObject has been assigned to a pointer, be
|
||||
careful not to delete the object manually.
|
||||
|
||||
This class uses an Atomic<int> value to hold the reference count, so that it
|
||||
the pointers can be passed between threads safely. For a faster but non-thread-safe
|
||||
version, use SingleThreadedSharedObject instead.
|
||||
|
||||
@see SharedObjectPtr, SharedObjectArray, SingleThreadedSharedObject
|
||||
*/
|
||||
class BEAST_API SharedObject : public Uncopyable
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Increments the object's reference count.
|
||||
|
||||
This is done automatically by the smart pointer, but is public just
|
||||
in case it's needed for nefarious purposes.
|
||||
*/
|
||||
inline void incReferenceCount() noexcept
|
||||
{
|
||||
++refCount;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
|
||||
If doDelete is true the object will be deleted when the reference
|
||||
count drops to zero. The delete is performed using the regular
|
||||
operator and does NOT go through the ContainerDeletePolicy.
|
||||
|
||||
The return value indicates if the reference count dropped to zero,
|
||||
so callers who know the derived type can use the ContainerDeletePolicy.
|
||||
*/
|
||||
inline bool decReferenceCount (bool doDelete = true) noexcept
|
||||
{
|
||||
bassert (getReferenceCount() > 0);
|
||||
if (--refCount == 0)
|
||||
{
|
||||
if (doDelete)
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns the object's current reference count. */
|
||||
inline int getReferenceCount() const noexcept { return refCount.get(); }
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates the reference-counted object (with an initial ref count of zero). */
|
||||
SharedObject()
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~SharedObject()
|
||||
{
|
||||
// it's dangerous to delete an object that's still referenced by something else!
|
||||
bassert (getReferenceCount() == 0);
|
||||
}
|
||||
|
||||
/** Resets the reference count to zero without deleting the object.
|
||||
You should probably never need to use this!
|
||||
*/
|
||||
void resetReferenceCount() noexcept
|
||||
{
|
||||
refCount = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Atomic <int> refCount;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Adds reference-counting to an object.
|
||||
|
||||
This is effectively a version of the SharedObject class, but which
|
||||
uses a non-atomic counter, and so is not thread-safe (but which will be more
|
||||
efficient).
|
||||
For more details on how to use it, see the SharedObject class notes.
|
||||
|
||||
@see SharedObject, SharedObjectPtr, SharedObjectArray
|
||||
*/
|
||||
class BEAST_API SingleThreadedSharedObject : public Uncopyable
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Increments the object's reference count.
|
||||
|
||||
This is done automatically by the smart pointer, but is public just
|
||||
in case it's needed for nefarious purposes.
|
||||
*/
|
||||
inline void incReferenceCount() noexcept
|
||||
{
|
||||
++refCount;
|
||||
}
|
||||
|
||||
/** Decreases the object's reference count.
|
||||
|
||||
If doDelete is true the object will be deleted when the reference
|
||||
count drops to zero. The delete is performed using the regular
|
||||
operator and does NOT go through the ContainerDeletePolicy.
|
||||
|
||||
The return value indicates if the reference count dropped to zero,
|
||||
so callers who know the derived type can use the ContainerDeletePolicy.
|
||||
*/
|
||||
inline bool decReferenceCount (bool doDelete = true) noexcept
|
||||
{
|
||||
bassert (getReferenceCount() > 0);
|
||||
if (--refCount == 0)
|
||||
{
|
||||
if (doDelete)
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the object's current reference count. */
|
||||
inline int getReferenceCount() const noexcept { return refCount; }
|
||||
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates the reference-counted object (with an initial ref count of zero). */
|
||||
SingleThreadedSharedObject() : refCount (0) {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~SingleThreadedSharedObject()
|
||||
{
|
||||
// it's dangerous to delete an object that's still referenced by something else!
|
||||
bassert (getReferenceCount() == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
int refCount;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A smart-pointer class which points to a reference-counted object.
|
||||
|
||||
The template parameter specifies the class of the object you want to point to - the easiest
|
||||
way to make a class reference-countable is to simply make it inherit from SharedObject,
|
||||
but if you need to, you could roll your own reference-countable class by implementing a pair of
|
||||
mathods called incReferenceCount() and decReferenceCount().
|
||||
|
||||
When using this class, you'll probably want to create a typedef to abbreviate the full
|
||||
templated name - e.g.
|
||||
@code typedef SharedObjectPtr<MyClass> MyClassPtr;@endcode
|
||||
|
||||
@see SharedObject, SharedObjectArray
|
||||
*/
|
||||
template <class Object>
|
||||
class SharedObjectPtr
|
||||
{
|
||||
public:
|
||||
/** The class being referenced by this pointer. */
|
||||
typedef Object ReferencedType;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a pointer to a null object. */
|
||||
inline SharedObjectPtr() noexcept
|
||||
: referencedObject (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a pointer to an object.
|
||||
|
||||
This will increment the object's reference-count if it is non-null.
|
||||
*/
|
||||
inline SharedObjectPtr (Object* const refCountedObject) noexcept
|
||||
: referencedObject (refCountedObject)
|
||||
{
|
||||
if (refCountedObject != nullptr)
|
||||
refCountedObject->incReferenceCount();
|
||||
}
|
||||
|
||||
/** Copies another pointer.
|
||||
This will increment the object's reference-count (if it is non-null).
|
||||
*/
|
||||
inline SharedObjectPtr (const SharedObjectPtr& other) noexcept
|
||||
: referencedObject (other.referencedObject)
|
||||
{
|
||||
if (referencedObject != nullptr)
|
||||
referencedObject->incReferenceCount();
|
||||
}
|
||||
|
||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
/** Takes-over the object from another pointer. */
|
||||
inline SharedObjectPtr (SharedObjectPtr&& other) noexcept
|
||||
: referencedObject (other.referencedObject)
|
||||
{
|
||||
other.referencedObject = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Copies another pointer.
|
||||
This will increment the object's reference-count (if it is non-null).
|
||||
*/
|
||||
template <class DerivedClass>
|
||||
inline SharedObjectPtr (const SharedObjectPtr<DerivedClass>& other) noexcept
|
||||
: referencedObject (static_cast <Object*> (other.get()))
|
||||
{
|
||||
if (referencedObject != nullptr)
|
||||
referencedObject->incReferenceCount();
|
||||
}
|
||||
|
||||
/** Changes this pointer to point at a different object.
|
||||
|
||||
The reference count of the old object is decremented, and it might be
|
||||
deleted if it hits zero. The new object's count is incremented.
|
||||
*/
|
||||
SharedObjectPtr& operator= (const SharedObjectPtr& other)
|
||||
{
|
||||
return operator= (other.referencedObject);
|
||||
}
|
||||
|
||||
/** Changes this pointer to point at a different object.
|
||||
|
||||
The reference count of the old object is decremented, and it might be
|
||||
deleted if it hits zero. The new object's count is incremented.
|
||||
*/
|
||||
template <class DerivedClass>
|
||||
SharedObjectPtr& operator= (const SharedObjectPtr<DerivedClass>& other)
|
||||
{
|
||||
return operator= (static_cast <Object*> (other.get()));
|
||||
}
|
||||
|
||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
/** Takes-over the object from another pointer. */
|
||||
SharedObjectPtr& operator= (SharedObjectPtr&& other)
|
||||
{
|
||||
std::swap (referencedObject, other.referencedObject);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Changes this pointer to point at a different object.
|
||||
|
||||
The reference count of the old object is decremented, and it might be
|
||||
deleted if it hits zero. The new object's count is incremented.
|
||||
*/
|
||||
SharedObjectPtr& operator= (Object* const newObject)
|
||||
{
|
||||
if (referencedObject != newObject)
|
||||
{
|
||||
if (newObject != nullptr)
|
||||
newObject->incReferenceCount();
|
||||
|
||||
Object* const oldObject = referencedObject;
|
||||
referencedObject = newObject;
|
||||
|
||||
if (oldObject != nullptr)
|
||||
{
|
||||
if (oldObject->decReferenceCount (false))
|
||||
ContainerDeletePolicy <Object>::destroy (oldObject);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Destructor.
|
||||
|
||||
This will decrement the object's reference-count, and may delete it if it
|
||||
gets to zero.
|
||||
*/
|
||||
inline ~SharedObjectPtr()
|
||||
{
|
||||
if (referencedObject != nullptr)
|
||||
{
|
||||
if (referencedObject->decReferenceCount (false))
|
||||
ContainerDeletePolicy <Object>::destroy (referencedObject);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the object that this pointer references.
|
||||
The pointer returned may be zero, of course.
|
||||
*/
|
||||
inline operator Object*() const noexcept
|
||||
{
|
||||
return referencedObject;
|
||||
}
|
||||
|
||||
// the -> operator is called on the referenced object
|
||||
inline Object* operator->() const noexcept
|
||||
{
|
||||
return referencedObject;
|
||||
}
|
||||
|
||||
/** Returns the object that this pointer references.
|
||||
The pointer returned may be zero, of course.
|
||||
*/
|
||||
inline Object* get() const noexcept
|
||||
{
|
||||
return referencedObject;
|
||||
}
|
||||
|
||||
/** Returns the object that this pointer references.
|
||||
The pointer returned may be zero, of course.
|
||||
*/
|
||||
inline Object* getObject() const noexcept
|
||||
{
|
||||
return referencedObject;
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Object* referencedObject;
|
||||
};
|
||||
|
||||
|
||||
/** Compares two SharedObjectPointers. */
|
||||
template <class Object>
|
||||
bool operator== (const SharedObjectPtr<Object>& object1, Object* const object2) noexcept
|
||||
{
|
||||
return object1.get() == object2;
|
||||
}
|
||||
|
||||
/** Compares two SharedObjectPointers. */
|
||||
template <class Object>
|
||||
bool operator== (const SharedObjectPtr<Object>& object1, const SharedObjectPtr<Object>& object2) noexcept
|
||||
{
|
||||
return object1.get() == object2.get();
|
||||
}
|
||||
|
||||
/** Compares two SharedObjectPointers. */
|
||||
template <class Object>
|
||||
bool operator== (Object* object1, SharedObjectPtr<Object>& object2) noexcept
|
||||
{
|
||||
return object1 == object2.get();
|
||||
}
|
||||
|
||||
/** Compares two SharedObjectPointers. */
|
||||
template <class Object>
|
||||
bool operator!= (const SharedObjectPtr<Object>& object1, const Object* object2) noexcept
|
||||
{
|
||||
return object1.get() != object2;
|
||||
}
|
||||
|
||||
/** Compares two SharedObjectPointers. */
|
||||
template <class Object>
|
||||
bool operator!= (const SharedObjectPtr<Object>& object1, SharedObjectPtr<Object>& object2) noexcept
|
||||
{
|
||||
return object1.get() != object2.get();
|
||||
}
|
||||
|
||||
/** Compares two SharedObjectPointers. */
|
||||
template <class Object>
|
||||
bool operator!= (Object* object1, SharedObjectPtr<Object>& object2) noexcept
|
||||
{
|
||||
return object1 != object2.get();
|
||||
}
|
||||
|
||||
|
||||
#endif // BEAST_REFERENCECOUNTEDOBJECT_H_INCLUDED
|
||||
@@ -107,7 +107,7 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
typedef SharedObjectPtr <Object> Ptr;
|
||||
typedef SharedPtr <Object> Ptr;
|
||||
|
||||
/** Retrieve a reference to the singleton.
|
||||
*/
|
||||
@@ -136,22 +136,20 @@ public:
|
||||
|
||||
inline void incReferenceCount () noexcept
|
||||
{
|
||||
m_refs.addref ();
|
||||
++m_refCount;
|
||||
}
|
||||
|
||||
inline bool decReferenceCount (bool = true) noexcept
|
||||
inline bool decReferenceCount (bool = false) noexcept
|
||||
{
|
||||
if (m_refs.release ())
|
||||
if (--m_refCount == 0)
|
||||
destroySingleton ();
|
||||
|
||||
// We let destroySingleton enforce the ContainerDeletePolicy
|
||||
return false;
|
||||
}
|
||||
|
||||
// Caller must synchronize.
|
||||
inline bool isBeingReferenced () const
|
||||
{
|
||||
return m_refs.isSignaled ();
|
||||
return m_refCount.get () != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -186,13 +184,13 @@ private:
|
||||
{
|
||||
bassert (m_lifetime != neverDestroyed);
|
||||
|
||||
ContainerDeletePolicy <Object>::destroy (static_cast <Object*>(this));
|
||||
delete static_cast <Object*> (this);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Lifetime const m_lifetime;
|
||||
AtomicCounter m_refs;
|
||||
Atomic <int> m_refCount;
|
||||
|
||||
private:
|
||||
static Object* s_instance;
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#ifndef BEAST_WEAKREFERENCE_H_INCLUDED
|
||||
#define BEAST_WEAKREFERENCE_H_INCLUDED
|
||||
|
||||
#include "beast_SharedObject.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This class acts as a pointer which will automatically become null if the object
|
||||
@@ -142,7 +139,7 @@ public:
|
||||
ObjectType* volatile owner;
|
||||
};
|
||||
|
||||
typedef SharedObjectPtr<SharedPointer> SharedRef;
|
||||
typedef SharedPtr<SharedPointer> SharedRef;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user