mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
New SharedSingleton, resolves destruction of objects with static storage duration.
This commit is contained in:
@@ -210,7 +210,7 @@
|
|||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_RecycledObjectPool.h" />
|
<ClInclude Include="..\..\modules\beast_core\memory\beast_RecycledObjectPool.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\memory\SharedObject.h" />
|
<ClInclude Include="..\..\modules\beast_core\memory\SharedObject.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_ScopedPointer.h" />
|
<ClInclude Include="..\..\modules\beast_core\memory\beast_ScopedPointer.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_SharedSingleton.h" />
|
<ClInclude Include="..\..\modules\beast_core\memory\SharedSingleton.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_StaticObject.h" />
|
<ClInclude Include="..\..\modules\beast_core\memory\beast_StaticObject.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_Uncopyable.h" />
|
<ClInclude Include="..\..\modules\beast_core\memory\beast_Uncopyable.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_WeakReference.h" />
|
<ClInclude Include="..\..\modules\beast_core\memory\beast_WeakReference.h" />
|
||||||
@@ -285,7 +285,6 @@
|
|||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_CallQueue.h" />
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_CallQueue.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_ConcurrentObject.h" />
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_ConcurrentObject.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_DeadlineTimer.h" />
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_DeadlineTimer.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_GlobalThreadGroup.h" />
|
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_InterruptibleThread.h" />
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_InterruptibleThread.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_Listeners.h" />
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_Listeners.h" />
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_ManualCallQueue.h" />
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_ManualCallQueue.h" />
|
||||||
|
|||||||
@@ -557,9 +557,6 @@
|
|||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_Uncopyable.h">
|
<ClInclude Include="..\..\modules\beast_core\memory\beast_Uncopyable.h">
|
||||||
<Filter>beast_core\memory</Filter>
|
<Filter>beast_core\memory</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\modules\beast_core\memory\beast_SharedSingleton.h">
|
|
||||||
<Filter>beast_core\memory</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\modules\beast_core\maths\beast_Interval.h">
|
<ClInclude Include="..\..\modules\beast_core\maths\beast_Interval.h">
|
||||||
<Filter>beast_core\maths</Filter>
|
<Filter>beast_core\maths</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -728,9 +725,6 @@
|
|||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_ConcurrentObject.h">
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_ConcurrentObject.h">
|
||||||
<Filter>beast_core\thread</Filter>
|
<Filter>beast_core\thread</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_GlobalThreadGroup.h">
|
|
||||||
<Filter>beast_core\thread</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\modules\beast_core\thread\beast_InterruptibleThread.h">
|
<ClInclude Include="..\..\modules\beast_core\thread\beast_InterruptibleThread.h">
|
||||||
<Filter>beast_core\thread</Filter>
|
<Filter>beast_core\thread</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -1028,6 +1022,9 @@
|
|||||||
<ClInclude Include="..\..\modules\beast_asio\basics\BufferType.h">
|
<ClInclude Include="..\..\modules\beast_asio\basics\BufferType.h">
|
||||||
<Filter>beast_asio\basics</Filter>
|
<Filter>beast_asio\basics</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\modules\beast_core\memory\SharedSingleton.h">
|
||||||
|
<Filter>beast_core\memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\modules\beast_core\containers\beast_AbstractFifo.cpp">
|
<ClCompile Include="..\..\modules\beast_core\containers\beast_AbstractFifo.cpp">
|
||||||
|
|||||||
7
TODO.txt
7
TODO.txt
@@ -2,9 +2,12 @@
|
|||||||
BEAST TODO
|
BEAST TODO
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
- Use new file naming convention
|
- Remove ReadWriteMutex and replace it with a CriticalSection
|
||||||
|
since the implementation is broken.
|
||||||
|
|
||||||
- Rename ReadWriteMutex to SharedMutex
|
- Rewrite SharedData to work with a CriticalSection
|
||||||
|
|
||||||
|
- Use new file naming convention
|
||||||
|
|
||||||
- Use SemanticVersion for beast version numbers to replace BEAST_VERSION
|
- Use SemanticVersion for beast version numbers to replace BEAST_VERSION
|
||||||
|
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
|
|||||||
#include "memory/beast_ByteOrder.h"
|
#include "memory/beast_ByteOrder.h"
|
||||||
#include "memory/beast_Memory.h"
|
#include "memory/beast_Memory.h"
|
||||||
#include "memory/beast_OptionalScopedPointer.h"
|
#include "memory/beast_OptionalScopedPointer.h"
|
||||||
#include "memory/beast_SharedSingleton.h"
|
#include "memory/SharedSingleton.h"
|
||||||
#include "memory/beast_WeakReference.h"
|
#include "memory/beast_WeakReference.h"
|
||||||
#include "memory/beast_RecycledObjectPool.h"
|
#include "memory/beast_RecycledObjectPool.h"
|
||||||
#include "misc/beast_Main.h"
|
#include "misc/beast_Main.h"
|
||||||
@@ -421,7 +421,6 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
|
|||||||
#include "thread/beast_InterruptibleThread.h"
|
#include "thread/beast_InterruptibleThread.h"
|
||||||
#include "thread/beast_ThreadGroup.h"
|
#include "thread/beast_ThreadGroup.h"
|
||||||
#include "thread/beast_CallQueue.h"
|
#include "thread/beast_CallQueue.h"
|
||||||
#include "thread/beast_GlobalThreadGroup.h"
|
|
||||||
#include "thread/beast_Listeners.h"
|
#include "thread/beast_Listeners.h"
|
||||||
#include "thread/beast_ManualCallQueue.h"
|
#include "thread/beast_ManualCallQueue.h"
|
||||||
#include "thread/beast_ParallelFor.h"
|
#include "thread/beast_ParallelFor.h"
|
||||||
|
|||||||
@@ -24,20 +24,15 @@
|
|||||||
// We need to make a shared singleton or else there are
|
// We need to make a shared singleton or else there are
|
||||||
// issues with the leak detector and order of detruction.
|
// issues with the leak detector and order of detruction.
|
||||||
//
|
//
|
||||||
class NonexistentHolder : public SharedSingleton <NonexistentHolder>
|
class NonexistentHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NonexistentHolder ()
|
static NonexistentHolder* getInstance()
|
||||||
: SharedSingleton <NonexistentHolder> (SingletonLifetime::persistAfterCreation)
|
|
||||||
{
|
{
|
||||||
|
return SharedSingleton <NonexistentHolder>::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
static NonexistentHolder* createInstance ()
|
File file;
|
||||||
{
|
|
||||||
return new NonexistentHolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
File const file;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
File const& File::nonexistent ()
|
File const& File::nonexistent ()
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
Requirement:
|
Requirement:
|
||||||
U* must be convertible to T*
|
U* must be convertible to T*
|
||||||
*/
|
*/
|
||||||
/// @{
|
/** @{ */
|
||||||
SharedPtr (T* t) noexcept
|
SharedPtr (T* t) noexcept
|
||||||
: m_p (acquire (t))
|
: m_p (acquire (t))
|
||||||
{
|
{
|
||||||
@@ -85,14 +85,14 @@ public:
|
|||||||
: m_p (acquire (u))
|
: m_p (acquire (u))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/// @}
|
/** @} */
|
||||||
|
|
||||||
/** Construct a container holding an object from another container.
|
/** Construct a container holding an object from another container.
|
||||||
This will increment the object's reference-count (if it is non-null).
|
This will increment the object's reference-count (if it is non-null).
|
||||||
Requirement:
|
Requirement:
|
||||||
U* must be convertible to T*
|
U* must be convertible to T*
|
||||||
*/
|
*/
|
||||||
/// @{
|
/** @{ */
|
||||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||||
SharedPtr (SharedPtr const& sp) noexcept
|
SharedPtr (SharedPtr const& sp) noexcept
|
||||||
: m_p (acquire (sp.get ()))
|
: m_p (acquire (sp.get ()))
|
||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
: m_p (acquire (sp.get ()))
|
: m_p (acquire (sp.get ()))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/// @}
|
/** @} */
|
||||||
|
|
||||||
/** Assign a different object to the container.
|
/** Assign a different object to the container.
|
||||||
The previous object beind held, if any, loses a reference count and
|
The previous object beind held, if any, loses a reference count and
|
||||||
@@ -113,7 +113,7 @@ public:
|
|||||||
Requirement:
|
Requirement:
|
||||||
U* must be convertible to T*
|
U* must be convertible to T*
|
||||||
*/
|
*/
|
||||||
/// @{
|
/** @{ */
|
||||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||||
SharedPtr& operator= (T* t)
|
SharedPtr& operator= (T* t)
|
||||||
{
|
{
|
||||||
@@ -126,10 +126,10 @@ public:
|
|||||||
{
|
{
|
||||||
return assign (u);
|
return assign (u);
|
||||||
}
|
}
|
||||||
/// @}
|
/** @} */
|
||||||
|
|
||||||
/** Assign an object from another container to this one. */
|
/** Assign an object from another container to this one. */
|
||||||
/// @{
|
/** @{ */
|
||||||
SharedPtr& operator= (SharedPtr const& sp)
|
SharedPtr& operator= (SharedPtr const& sp)
|
||||||
{
|
{
|
||||||
return assign (sp.get ());
|
return assign (sp.get ());
|
||||||
@@ -141,7 +141,7 @@ public:
|
|||||||
{
|
{
|
||||||
return assign (sp.get ());
|
return assign (sp.get ());
|
||||||
}
|
}
|
||||||
/// @}
|
/** @} */
|
||||||
|
|
||||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||||
/** Construct a container with an object transferred from another container.
|
/** Construct a container with an object transferred from another container.
|
||||||
@@ -149,7 +149,7 @@ public:
|
|||||||
Requires:
|
Requires:
|
||||||
U* must be convertible to T*
|
U* must be convertible to T*
|
||||||
*/
|
*/
|
||||||
/// @{
|
/** @{ */
|
||||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||||
SharedPtr (SharedPtr && sp) noexcept
|
SharedPtr (SharedPtr && sp) noexcept
|
||||||
: m_p (sp.swap <T> (nullptr))
|
: m_p (sp.swap <T> (nullptr))
|
||||||
@@ -162,14 +162,14 @@ public:
|
|||||||
: m_p (sp.swap <U> (nullptr))
|
: m_p (sp.swap <U> (nullptr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/// @}
|
/** @} */
|
||||||
|
|
||||||
/** Transfer ownership of another object to this container.
|
/** Transfer ownership of another object to this container.
|
||||||
The originating container loses its reference to the object.
|
The originating container loses its reference to the object.
|
||||||
Requires:
|
Requires:
|
||||||
U* must be convertible to T*
|
U* must be convertible to T*
|
||||||
*/
|
*/
|
||||||
/// @{
|
/** @{ */
|
||||||
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
#if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS
|
||||||
SharedPtr& operator= (SharedPtr && sp)
|
SharedPtr& operator= (SharedPtr && sp)
|
||||||
{
|
{
|
||||||
@@ -182,7 +182,7 @@ public:
|
|||||||
{
|
{
|
||||||
return assign (sp.swap <U> (nullptr));
|
return assign (sp.swap <U> (nullptr));
|
||||||
}
|
}
|
||||||
/// @}
|
/** @} */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Destroy the container and release the held reference, if any.
|
/** Destroy the container and release the held reference, if any.
|
||||||
@@ -262,8 +262,8 @@ private:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/// SharedPtr comparisons.
|
/** SharedPtr comparisons. */
|
||||||
/// @{
|
/** @{ */
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator== (SharedPtr <T> const& lhs, U* const rhs) noexcept
|
bool operator== (SharedPtr <T> const& lhs, U* const rhs) noexcept
|
||||||
{
|
{
|
||||||
@@ -277,28 +277,28 @@ bool operator== (SharedPtr <T> const& lhs, SharedPtr <U> const& rhs) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator== (T const* lhs, SharedPtr<T> const& rhs) noexcept
|
bool operator== (T const* lhs, SharedPtr <U> const& rhs) noexcept
|
||||||
{
|
{
|
||||||
return lhs == rhs.get();
|
return lhs == rhs.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator!= (SharedPtr <T> const& lhs, T const* rhs) noexcept
|
bool operator!= (SharedPtr <T> const& lhs, U const* rhs) noexcept
|
||||||
{
|
{
|
||||||
return lhs.get() != rhs;
|
return lhs.get() != rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator!= (SharedPtr <T> const& lhs, SharedPtr <T> const& rhs) noexcept
|
bool operator!= (SharedPtr <T> const& lhs, SharedPtr <U> const& rhs) noexcept
|
||||||
{
|
{
|
||||||
return lhs.get() != rhs.get();
|
return lhs.get() != rhs.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator!= (T const* lhs, SharedPtr<T> const& rhs) noexcept
|
bool operator!= (T const* lhs, SharedPtr <U> const& rhs) noexcept
|
||||||
{
|
{
|
||||||
return lhs != rhs.get();
|
return lhs != rhs.get();
|
||||||
}
|
}
|
||||||
/// @}
|
/** @} */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#ifndef BEAST_REFERENCECOUNTEDSINGLETON_H_INCLUDED
|
#ifndef BEAST_SHAREDSINGLETON_H_INCLUDED
|
||||||
#define BEAST_REFERENCECOUNTEDSINGLETON_H_INCLUDED
|
#define BEAST_SHAREDSINGLETON_H_INCLUDED
|
||||||
|
|
||||||
/** Thread-safe singleton which comes into existence on first use. Use this
|
/** Thread-safe singleton which comes into existence on first use. Use this
|
||||||
instead of creating objects with static storage duration. These singletons
|
instead of creating objects with static storage duration. These singletons
|
||||||
@@ -52,11 +52,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
createOnDemand,
|
createOnDemand,
|
||||||
|
|
||||||
/** Like createOnDemand, but after the Singleton is destroyed an
|
|
||||||
exception will be thrown if an attempt is made to create it again.
|
|
||||||
*/
|
|
||||||
createOnDemandOnce,
|
|
||||||
|
|
||||||
/** The singleton is created on first use and persists until program exit.
|
/** The singleton is created on first use and persists until program exit.
|
||||||
*/
|
*/
|
||||||
persistAfterCreation,
|
persistAfterCreation,
|
||||||
@@ -71,131 +66,128 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Wraps object to produce a reference counted singleton. */
|
||||||
template <class Object>
|
template <class Object>
|
||||||
class SharedSingleton
|
class SharedSingleton
|
||||||
: public SingletonLifetime
|
: public Object
|
||||||
, private PerformedAtExit
|
, private SharedObject
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
typedef SpinLock LockType;
|
|
||||||
|
|
||||||
/** Create the singleton.
|
|
||||||
|
|
||||||
@param lifetime The lifetime management option.
|
|
||||||
*/
|
|
||||||
explicit SharedSingleton (Lifetime const lifetime)
|
|
||||||
: m_lifetime (lifetime)
|
|
||||||
{
|
|
||||||
bassert (s_instance == nullptr);
|
|
||||||
|
|
||||||
if (m_lifetime == persistAfterCreation ||
|
|
||||||
m_lifetime == neverDestroyed)
|
|
||||||
{
|
|
||||||
incReferenceCount ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~SharedSingleton ()
|
|
||||||
{
|
|
||||||
bassert (s_instance == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef SharedPtr <Object> Ptr;
|
typedef SharedPtr <SharedSingleton <Object> > Ptr;
|
||||||
|
|
||||||
/** Retrieve a reference to the singleton.
|
static Ptr getInstance (SingletonLifetime::Lifetime lifetime
|
||||||
*/
|
= SingletonLifetime::persistAfterCreation)
|
||||||
static Ptr getInstance ()
|
|
||||||
{
|
{
|
||||||
Ptr instance;
|
StaticData& staticData (getStaticData ());
|
||||||
|
SharedSingleton* instance = staticData.instance;
|
||||||
instance = s_instance;
|
|
||||||
|
|
||||||
if (instance == nullptr)
|
if (instance == nullptr)
|
||||||
{
|
{
|
||||||
LockType::ScopedLockType lock (*s_mutex);
|
LockType::ScopedLockType lock (staticData.mutex);
|
||||||
|
instance = staticData.instance;
|
||||||
instance = s_instance;
|
|
||||||
|
|
||||||
if (instance == nullptr)
|
if (instance == nullptr)
|
||||||
{
|
{
|
||||||
s_instance = Object::createInstance ();
|
staticData.instance = &staticData.object;
|
||||||
|
::new (staticData.instance) SharedSingleton (lifetime);
|
||||||
instance = s_instance;
|
instance = staticData.instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void incReferenceCount () noexcept
|
|
||||||
{
|
|
||||||
++m_refCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void decReferenceCount () noexcept
|
|
||||||
{
|
|
||||||
if (--m_refCount == 0)
|
|
||||||
destroySingleton ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Caller must synchronize.
|
|
||||||
inline bool isBeingReferenced () const
|
|
||||||
{
|
|
||||||
return m_refCount.get () != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
explicit SharedSingleton (SingletonLifetime::Lifetime lifetime)
|
||||||
|
: m_lifetime (lifetime)
|
||||||
|
, m_exitHook (this)
|
||||||
|
{
|
||||||
|
if (m_lifetime == SingletonLifetime::persistAfterCreation)
|
||||||
|
this->incReferenceCount ();
|
||||||
|
}
|
||||||
|
|
||||||
|
~SharedSingleton ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void performAtExit ()
|
void performAtExit ()
|
||||||
{
|
{
|
||||||
if (m_lifetime == SingletonLifetime::persistAfterCreation)
|
if (m_lifetime == SingletonLifetime::persistAfterCreation)
|
||||||
decReferenceCount ();
|
this->decReferenceCount ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroySingleton ()
|
void destroy () const
|
||||||
{
|
{
|
||||||
bool destroy;
|
bool callDestructor;
|
||||||
|
|
||||||
// Handle the condition where one thread is releasing the last
|
// Handle the condition where one thread is releasing the last
|
||||||
// reference just as another thread is trying to acquire it.
|
// reference just as another thread is trying to acquire it.
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
LockType::ScopedLockType lock (*s_mutex);
|
StaticData& staticData (getStaticData ());
|
||||||
|
LockType::ScopedLockType lock (staticData.mutex);
|
||||||
|
|
||||||
if (isBeingReferenced ())
|
if (this->getReferenceCount() != 0)
|
||||||
{
|
{
|
||||||
destroy = false;
|
callDestructor = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
destroy = true;
|
callDestructor = true;
|
||||||
s_instance = 0;
|
staticData.instance = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destroy)
|
if (callDestructor)
|
||||||
{
|
{
|
||||||
bassert (m_lifetime != neverDestroyed);
|
bassert (m_lifetime != SingletonLifetime::neverDestroyed);
|
||||||
|
|
||||||
delete static_cast <Object*> (this);
|
this->~SharedSingleton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
typedef SpinLock LockType;
|
||||||
Lifetime const m_lifetime;
|
|
||||||
Atomic <int> m_refCount;
|
|
||||||
|
|
||||||
private:
|
class ExitHook
|
||||||
static Object* s_instance;
|
{
|
||||||
static Static::Storage <LockType, SharedSingleton <Object> > s_mutex;
|
public:
|
||||||
|
explicit ExitHook (SharedSingleton* owner)
|
||||||
|
: m_owner (owner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void performaAtExit ()
|
||||||
|
{
|
||||||
|
m_owner->performAtExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SharedSingleton* m_owner;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This structure gets zero-filled at static initialization time.
|
||||||
|
// No constructors are called.
|
||||||
|
//
|
||||||
|
struct StaticData
|
||||||
|
{
|
||||||
|
LockType mutex;
|
||||||
|
SharedSingleton* instance;
|
||||||
|
SharedSingleton object;
|
||||||
|
|
||||||
|
private:
|
||||||
|
StaticData();
|
||||||
|
~StaticData();
|
||||||
|
};
|
||||||
|
|
||||||
|
static StaticData& getStaticData ()
|
||||||
|
{
|
||||||
|
static uint8 storage [sizeof (StaticData)];
|
||||||
|
return *(reinterpret_cast <StaticData*> (&storage [0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class SharedPtr <SharedSingleton>;
|
||||||
|
|
||||||
|
SingletonLifetime::Lifetime m_lifetime;
|
||||||
|
ExitHook m_exitHook;
|
||||||
};
|
};
|
||||||
/** @{ */
|
|
||||||
|
|
||||||
template <class Object>
|
//------------------------------------------------------------------------------
|
||||||
Object* SharedSingleton <Object>::s_instance;
|
|
||||||
|
|
||||||
template <class Object>
|
|
||||||
Static::Storage <typename SharedSingleton <Object>::LockType, SharedSingleton <Object> >
|
|
||||||
SharedSingleton <Object>::s_mutex;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
@ingroup beast_concurrent
|
@ingroup beast_concurrent
|
||||||
*/
|
*/
|
||||||
template <class Tag>
|
template <class Tag>
|
||||||
class GlobalFifoFreeStore : public SharedSingleton <GlobalFifoFreeStore <Tag> >
|
class GlobalFifoFreeStore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline void* allocate (size_t bytes)
|
inline void* allocate (size_t bytes)
|
||||||
@@ -40,15 +40,15 @@ public:
|
|||||||
FifoFreeStoreType::deallocate (p);
|
FifoFreeStoreType::deallocate (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GlobalFifoFreeStore* createInstance ()
|
typedef SharedPtr <SharedSingleton <GlobalFifoFreeStore> > Ptr;
|
||||||
|
|
||||||
|
static Ptr getInstance ()
|
||||||
{
|
{
|
||||||
return new GlobalFifoFreeStore;
|
return SharedSingleton <GlobalFifoFreeStore>::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GlobalFifoFreeStore ()
|
GlobalFifoFreeStore ()
|
||||||
: SharedSingleton <GlobalFifoFreeStore <Tag> >
|
|
||||||
(SingletonLifetime::persistAfterCreation)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ static const size_t globalPageBytes = 8 * 1024;
|
|||||||
}
|
}
|
||||||
|
|
||||||
GlobalPagedFreeStore::GlobalPagedFreeStore ()
|
GlobalPagedFreeStore::GlobalPagedFreeStore ()
|
||||||
: SharedSingleton <GlobalPagedFreeStore> (SingletonLifetime::persistAfterCreation)
|
: m_allocator (globalPageBytes)
|
||||||
, m_allocator (globalPageBytes)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +35,9 @@ GlobalPagedFreeStore::~GlobalPagedFreeStore ()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalPagedFreeStore* GlobalPagedFreeStore::createInstance ()
|
GlobalPagedFreeStore::Ptr GlobalPagedFreeStore::getInstance ()
|
||||||
{
|
{
|
||||||
return new GlobalPagedFreeStore;
|
return SharedSingleton <GlobalPagedFreeStore>::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,7 @@
|
|||||||
|
|
||||||
@ingroup beast_concurrent
|
@ingroup beast_concurrent
|
||||||
*/
|
*/
|
||||||
class BEAST_API GlobalPagedFreeStore
|
class BEAST_API GlobalPagedFreeStore : public LeakChecked <GlobalPagedFreeStore>
|
||||||
: public SharedSingleton <GlobalPagedFreeStore>
|
|
||||||
, LeakChecked <GlobalPagedFreeStore>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GlobalPagedFreeStore ();
|
GlobalPagedFreeStore ();
|
||||||
@@ -50,7 +48,9 @@ public:
|
|||||||
PagedFreeStore::deallocate (p);
|
PagedFreeStore::deallocate (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GlobalPagedFreeStore* createInstance ();
|
typedef SharedPtr <SharedSingleton <GlobalPagedFreeStore> > Ptr;
|
||||||
|
|
||||||
|
static Ptr getInstance ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PagedFreeStore m_allocator;
|
PagedFreeStore m_allocator;
|
||||||
|
|||||||
@@ -17,18 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
class DeadlineTimer::Manager
|
class DeadlineTimer::Manager : protected Thread
|
||||||
: public SharedSingleton <DeadlineTimer::Manager>
|
|
||||||
, protected Thread
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
typedef CriticalSection LockType;
|
typedef CriticalSection LockType;
|
||||||
typedef List <DeadlineTimer> Items;
|
typedef List <DeadlineTimer> Items;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Manager ()
|
Manager () : Thread ("DeadlineTimer::Manager")
|
||||||
: SharedSingleton <Manager> (SingletonLifetime::persistAfterCreation)
|
|
||||||
, Thread ("DeadlineTimer::Manager")
|
|
||||||
{
|
{
|
||||||
startThread ();
|
startThread ();
|
||||||
}
|
}
|
||||||
@@ -200,11 +196,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Manager* createInstance ()
|
|
||||||
{
|
|
||||||
return new Manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CriticalSection m_mutex;
|
CriticalSection m_mutex;
|
||||||
Items m_items;
|
Items m_items;
|
||||||
@@ -214,7 +205,8 @@ private:
|
|||||||
|
|
||||||
DeadlineTimer::DeadlineTimer (Listener* listener)
|
DeadlineTimer::DeadlineTimer (Listener* listener)
|
||||||
: m_listener (listener)
|
: m_listener (listener)
|
||||||
, m_manager (Manager::getInstance ())
|
, m_manager (SharedSingleton <Manager>::getInstance (
|
||||||
|
SingletonLifetime::persistAfterCreation))
|
||||||
, m_isActive (false)
|
, m_isActive (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ private:
|
|||||||
class Manager;
|
class Manager;
|
||||||
|
|
||||||
Listener* const m_listener;
|
Listener* const m_listener;
|
||||||
SharedPtr <Manager> m_manager;
|
SharedPtr <SharedSingleton <Manager> > m_manager;
|
||||||
bool m_isActive;
|
bool m_isActive;
|
||||||
Time m_notificationTime;
|
Time m_notificationTime;
|
||||||
double m_secondsRecurring; // non zero if recurring
|
double m_secondsRecurring; // non zero if recurring
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.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_GLOBALTHREADGROUP_H_INCLUDED
|
|
||||||
#define BEAST_GLOBALTHREADGROUP_H_INCLUDED
|
|
||||||
|
|
||||||
/*============================================================================*/
|
|
||||||
/**
|
|
||||||
A ThreadGroup singleton.
|
|
||||||
|
|
||||||
@see ThreadGroup
|
|
||||||
|
|
||||||
@ingroup beast_concurrent
|
|
||||||
*/
|
|
||||||
class BEAST_API GlobalThreadGroup : public ThreadGroup,
|
|
||||||
public SharedSingleton <GlobalThreadGroup>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
friend class SharedSingleton <GlobalThreadGroup>;
|
|
||||||
|
|
||||||
GlobalThreadGroup ()
|
|
||||||
: SharedSingleton <GlobalThreadGroup> (
|
|
||||||
SingletonLifetime::persistAfterCreation)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static GlobalThreadGroup* createInstance ()
|
|
||||||
{
|
|
||||||
return new GlobalThreadGroup;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -616,7 +616,7 @@ void ListenersBase::remove_void (void* const listener)
|
|||||||
|
|
||||||
// Remove it from the list and manually release
|
// Remove it from the list and manually release
|
||||||
// the reference since the list uses raw pointers.
|
// the reference since the list uses raw pointers.
|
||||||
m_groups.erase (m_groups.iterator_to (*group);
|
m_groups.erase (m_groups.iterator_to (*group));
|
||||||
group->decReferenceCount ();
|
group->decReferenceCount ();
|
||||||
|
|
||||||
// It is still possible for the group to exist at this
|
// It is still possible for the group to exist at this
|
||||||
|
|||||||
@@ -60,10 +60,9 @@ public:
|
|||||||
It is best to keep this object around instead of creating and destroying
|
It is best to keep this object around instead of creating and destroying
|
||||||
it every time you need to run a loop.
|
it every time you need to run a loop.
|
||||||
|
|
||||||
@param pool The ThreadGroup to use. If this is omitted then a singleton
|
@param pool The ThreadGroup to use.
|
||||||
ThreadGroup is used which contains one thread per CPU.
|
|
||||||
*/
|
*/
|
||||||
explicit ParallelFor (ThreadGroup& pool = *GlobalThreadGroup::getInstance ());
|
explicit ParallelFor (ThreadGroup& pool);
|
||||||
|
|
||||||
/** Determine the number of threads in the group.
|
/** Determine the number of threads in the group.
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
class Sqlite3;
|
class Sqlite3;
|
||||||
SharedPtr <Sqlite3> m_instance;
|
SharedPtr <SharedSingleton <Sqlite3> > m_instance;
|
||||||
bool m_bInTransaction;
|
bool m_bInTransaction;
|
||||||
sqlite3* m_connection;
|
sqlite3* m_connection;
|
||||||
String m_fileName;
|
String m_fileName;
|
||||||
|
|||||||
@@ -60,12 +60,10 @@
|
|||||||
namespace sqdb
|
namespace sqdb
|
||||||
{
|
{
|
||||||
|
|
||||||
class session::Sqlite3 : public SharedSingleton <Sqlite3>
|
class session::Sqlite3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class SharedSingleton <Sqlite3>;
|
Sqlite3()
|
||||||
|
|
||||||
Sqlite3() : SharedSingleton <Sqlite3> (SingletonLifetime::persistAfterCreation)
|
|
||||||
{
|
{
|
||||||
int threadSafe = sqlite3_threadsafe();
|
int threadSafe = sqlite3_threadsafe();
|
||||||
|
|
||||||
@@ -84,30 +82,25 @@ public:
|
|||||||
{
|
{
|
||||||
sqlite3_shutdown();
|
sqlite3_shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Sqlite3* createInstance()
|
|
||||||
{
|
|
||||||
return new Sqlite3;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
session::session()
|
session::session()
|
||||||
: prepare(this)
|
: prepare (this)
|
||||||
, m_instance(Sqlite3::getInstance())
|
, m_instance (SharedSingleton <Sqlite3>::getInstance ())
|
||||||
, m_bInTransaction(false)
|
, m_bInTransaction (false)
|
||||||
, m_connection(nullptr)
|
, m_connection (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
session::session(const session& deferredClone)
|
session::session(const session& deferredClone)
|
||||||
: prepare(this)
|
: prepare (this)
|
||||||
, m_instance(Sqlite3::getInstance())
|
, m_instance (SharedSingleton <Sqlite3>::getInstance ())
|
||||||
, m_bInTransaction(false)
|
, m_bInTransaction (false)
|
||||||
, m_connection(nullptr)
|
, m_connection (nullptr)
|
||||||
, m_fileName(deferredClone.m_fileName)
|
, m_fileName (deferredClone.m_fileName)
|
||||||
, m_connectString(deferredClone.m_connectString)
|
, m_connectString (deferredClone.m_connectString)
|
||||||
{
|
{
|
||||||
// shouldn't be needed since deferredClone did it
|
// shouldn't be needed since deferredClone did it
|
||||||
//Sqlite::initialize();
|
//Sqlite::initialize();
|
||||||
|
|||||||
Reference in New Issue
Block a user