mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 22:15:52 +00:00
Remove obsolete classes:
Legacy workarounds for Visual Studio non thread-safe initialization of function local objects with static storage duration are removed: * Remove LeakChecked * Remove StaticObject * Remove SharedSingleton
This commit is contained in:
committed by
Tom Ritchford
parent
11c472d701
commit
df89999891
@@ -52,9 +52,7 @@
|
||||
#include <beast/utility/Debug.h>
|
||||
#include <beast/utility/Error.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/utility/LeakChecked.h>
|
||||
#include <beast/utility/PropertyStream.h>
|
||||
#include <beast/utility/StaticObject.h>
|
||||
|
||||
#include <beast/module/core/system/StandardIncludes.h>
|
||||
|
||||
@@ -144,7 +142,6 @@ class FileOutputStream;
|
||||
#include <beast/module/core/streams/FileInputSource.h>
|
||||
#include <beast/module/core/streams/OutputStream.h>
|
||||
#include <beast/module/core/files/FileOutputStream.h>
|
||||
#include <beast/module/core/memory/SharedSingleton.h>
|
||||
#include <beast/module/core/streams/MemoryOutputStream.h>
|
||||
|
||||
#include <beast/module/core/system/SystemStats.h>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace beast {
|
||||
|
||||
It can also guess how far it's got using a wildly inaccurate algorithm.
|
||||
*/
|
||||
class DirectoryIterator : LeakChecked <DirectoryIterator>
|
||||
class DirectoryIterator
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class NativeIterator : LeakChecked <NativeIterator>
|
||||
class NativeIterator
|
||||
{
|
||||
public:
|
||||
NativeIterator (const File& directory, const String& wildCard);
|
||||
|
||||
@@ -22,29 +22,16 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
#include <beast/utility/static_initializer.h>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
namespace beast {
|
||||
|
||||
// We need to make a shared singleton or else there are
|
||||
// issues with the leak detector and order of detruction.
|
||||
//
|
||||
class NonexistentHolder
|
||||
File const& File::nonexistent()
|
||||
{
|
||||
public:
|
||||
static NonexistentHolder* getInstance()
|
||||
{
|
||||
return SharedSingleton <NonexistentHolder>::getInstance();
|
||||
}
|
||||
|
||||
File file;
|
||||
};
|
||||
|
||||
File const& File::nonexistent ()
|
||||
{
|
||||
return NonexistentHolder::getInstance ()->file;
|
||||
static beast::static_initializer<File> instance;
|
||||
return *instance;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace beast
|
||||
*/
|
||||
class FileInputStream
|
||||
: public InputStream
|
||||
, LeakChecked <FileInputStream>
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace beast
|
||||
*/
|
||||
class FileOutputStream
|
||||
: public OutputStream
|
||||
, LeakChecked <FileOutputStream>
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#define BEAST_MODULE_CORE_MEMORY_MEMORYBLOCK_H_INCLUDED
|
||||
|
||||
#include <beast/HeapBlock.h>
|
||||
#include <beast/utility/LeakChecked.h>
|
||||
#include <beast/strings/String.h>
|
||||
|
||||
namespace beast {
|
||||
@@ -35,7 +34,7 @@ namespace beast {
|
||||
A class to hold a resizable block of raw data.
|
||||
|
||||
*/
|
||||
class MemoryBlock : LeakChecked <MemoryBlock>
|
||||
class MemoryBlock
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -1,205 +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_MODULE_CORE_MEMORY_SHAREDSINGLETON_H_INCLUDED
|
||||
#define BEAST_MODULE_CORE_MEMORY_SHAREDSINGLETON_H_INCLUDED
|
||||
|
||||
#include <beast/threads/SpinLock.h>
|
||||
#include <beast/smart_ptr/SharedPtr.h>
|
||||
#include <beast/module/core/time/AtExitHook.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
/** Thread-safe singleton which comes into existence on first use. Use this
|
||||
instead of creating objects with static storage duration. These singletons
|
||||
are automatically reference counted, so if you hold a pointer to it in every
|
||||
object that depends on it, the order of destruction of objects is assured
|
||||
to be correct.
|
||||
|
||||
Object Requirements:
|
||||
DefaultConstructible
|
||||
TriviallyDestructible (when lifetime == neverDestroyed)
|
||||
Destructible
|
||||
|
||||
@class SharedSingleton
|
||||
@ingroup beast_core
|
||||
*/
|
||||
/** @{ */
|
||||
class SingletonLifetime
|
||||
{
|
||||
public:
|
||||
// It would be nice if we didn't have to qualify the enumeration but
|
||||
// Argument Dependent Lookup is inapplicable here because:
|
||||
//
|
||||
// "Base classes dependent on a template parameter aren't part of lookup."
|
||||
// - ville
|
||||
//
|
||||
|
||||
/** Construction options for SharedSingleton
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
enum Lifetime
|
||||
{
|
||||
/** Created on first use, destroyed when the last reference is removed.
|
||||
*/
|
||||
createOnDemand,
|
||||
|
||||
/** The singleton is created on first use and persists until program exit.
|
||||
*/
|
||||
persistAfterCreation,
|
||||
|
||||
/** The singleton is created when needed and never destroyed.
|
||||
|
||||
This is useful for applications which do not have a clean exit.
|
||||
*/
|
||||
neverDestroyed
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Wraps object to produce a reference counted singleton. */
|
||||
template <class Object>
|
||||
class SharedSingleton
|
||||
: public Object
|
||||
, private SharedObject
|
||||
{
|
||||
public:
|
||||
typedef SharedPtr <SharedSingleton <Object> > Ptr;
|
||||
|
||||
static Ptr get (SingletonLifetime::Lifetime lifetime
|
||||
= SingletonLifetime::persistAfterCreation)
|
||||
{
|
||||
StaticData& staticData (getStaticData ());
|
||||
SharedSingleton* instance = staticData.instance;
|
||||
if (instance == nullptr)
|
||||
{
|
||||
std::lock_guard <LockType> lock (staticData.mutex);
|
||||
instance = staticData.instance;
|
||||
if (instance == nullptr)
|
||||
{
|
||||
bassert (lifetime == SingletonLifetime::createOnDemand || ! staticData.destructorCalled);
|
||||
staticData.instance = &staticData.object;
|
||||
new (staticData.instance) SharedSingleton (lifetime);
|
||||
std::atomic_thread_fence (std::memory_order_seq_cst);
|
||||
instance = staticData.instance;
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// DEPRECATED LEGACY FUNCTION NAME
|
||||
static Ptr getInstance (SingletonLifetime::Lifetime lifetime
|
||||
= SingletonLifetime::persistAfterCreation)
|
||||
{
|
||||
return get (lifetime);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit SharedSingleton (SingletonLifetime::Lifetime lifetime)
|
||||
: m_lifetime (lifetime)
|
||||
, m_exitHook (this)
|
||||
{
|
||||
if (m_lifetime == SingletonLifetime::persistAfterCreation ||
|
||||
m_lifetime == SingletonLifetime::neverDestroyed)
|
||||
this->incReferenceCount ();
|
||||
}
|
||||
|
||||
~SharedSingleton ()
|
||||
{
|
||||
}
|
||||
|
||||
void onExit ()
|
||||
{
|
||||
if (m_lifetime == SingletonLifetime::persistAfterCreation)
|
||||
this->decReferenceCount ();
|
||||
}
|
||||
|
||||
void destroy () const
|
||||
{
|
||||
bool callDestructor;
|
||||
|
||||
// Handle the condition where one thread is releasing the last
|
||||
// reference just as another thread is trying to acquire it.
|
||||
//
|
||||
{
|
||||
StaticData& staticData (getStaticData ());
|
||||
std::lock_guard <LockType> lock (staticData.mutex);
|
||||
|
||||
if (this->getReferenceCount() != 0)
|
||||
{
|
||||
callDestructor = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
callDestructor = true;
|
||||
staticData.instance = nullptr;
|
||||
staticData.destructorCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (callDestructor)
|
||||
{
|
||||
bassert (m_lifetime != SingletonLifetime::neverDestroyed);
|
||||
|
||||
this->~SharedSingleton();
|
||||
}
|
||||
}
|
||||
|
||||
typedef SpinLock LockType;
|
||||
|
||||
// This structure gets zero-filled at static initialization time.
|
||||
// No constructors are called.
|
||||
//
|
||||
class StaticData
|
||||
{
|
||||
public:
|
||||
LockType mutex;
|
||||
SharedSingleton* instance;
|
||||
SharedSingleton object;
|
||||
bool destructorCalled;
|
||||
|
||||
StaticData() = delete;
|
||||
StaticData(StaticData const&) = delete;
|
||||
StaticData& operator= (StaticData const&) = delete;
|
||||
~StaticData() = delete;
|
||||
};
|
||||
|
||||
static StaticData& getStaticData ()
|
||||
{
|
||||
static std::uint8_t storage [sizeof (StaticData)];
|
||||
return *(reinterpret_cast <StaticData*> (&storage [0]));
|
||||
}
|
||||
|
||||
friend class SharedPtr <SharedSingleton>;
|
||||
friend class AtExitMemberHook <SharedSingleton>;
|
||||
|
||||
SingletonLifetime::Lifetime m_lifetime;
|
||||
AtExitMemberHook <SharedSingleton> m_exitHook;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -399,7 +399,6 @@ bool File::setAsCurrentWorkingDirectory() const
|
||||
|
||||
//==============================================================================
|
||||
class DirectoryIterator::NativeIterator::Pimpl
|
||||
: LeakChecked <DirectoryIterator::NativeIterator::Pimpl>
|
||||
{
|
||||
public:
|
||||
Pimpl (const File& directory, const String& wildCard)
|
||||
|
||||
@@ -35,7 +35,6 @@ namespace beast
|
||||
*/
|
||||
class FileInputSource
|
||||
: public InputSource
|
||||
, LeakChecked <FileInputSource>
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace beast
|
||||
|
||||
@see FileInputSource
|
||||
*/
|
||||
class InputSource : LeakChecked <InputSource>
|
||||
class InputSource
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -38,7 +38,6 @@ class MemoryBlock;
|
||||
@see OutputStream, FileInputStream
|
||||
*/
|
||||
class InputStream
|
||||
: LeakChecked <InputStream>
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
|
||||
@@ -43,7 +43,6 @@ namespace beast
|
||||
*/
|
||||
class MemoryOutputStream
|
||||
: public OutputStream
|
||||
, LeakChecked <MemoryOutputStream>
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/utility/static_initializer.h>
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
class DeadlineTimer::Manager
|
||||
: public LeakChecked <Manager>
|
||||
, protected Thread
|
||||
: protected Thread
|
||||
{
|
||||
private:
|
||||
typedef CriticalSection LockType;
|
||||
@@ -42,6 +43,14 @@ public:
|
||||
bassert (m_items.empty ());
|
||||
}
|
||||
|
||||
static
|
||||
Manager&
|
||||
instance()
|
||||
{
|
||||
static beast::static_initializer<Manager> m;
|
||||
return *m;
|
||||
}
|
||||
|
||||
// Okay to call on an active timer.
|
||||
// However, an extra notification may still happen due to concurrency.
|
||||
//
|
||||
@@ -210,19 +219,18 @@ private:
|
||||
|
||||
DeadlineTimer::DeadlineTimer (Listener* listener)
|
||||
: m_listener (listener)
|
||||
, m_manager (SharedSingleton <Manager>::getInstance ())
|
||||
, m_isActive (false)
|
||||
{
|
||||
}
|
||||
|
||||
DeadlineTimer::~DeadlineTimer ()
|
||||
{
|
||||
m_manager->deactivate (*this);
|
||||
Manager::instance().deactivate (*this);
|
||||
}
|
||||
|
||||
void DeadlineTimer::cancel ()
|
||||
{
|
||||
m_manager->deactivate (*this);
|
||||
Manager::instance().deactivate (*this);
|
||||
}
|
||||
|
||||
void DeadlineTimer::setExpiration (double secondsUntilDeadline)
|
||||
@@ -232,7 +240,7 @@ void DeadlineTimer::setExpiration (double secondsUntilDeadline)
|
||||
RelativeTime const when (
|
||||
RelativeTime::fromStartup() + secondsUntilDeadline);
|
||||
|
||||
m_manager->activate (*this, 0, when);
|
||||
Manager::instance().activate (*this, 0, when);
|
||||
}
|
||||
|
||||
void DeadlineTimer::setRecurringExpiration (double secondsUntilDeadline)
|
||||
@@ -242,7 +250,7 @@ void DeadlineTimer::setRecurringExpiration (double secondsUntilDeadline)
|
||||
RelativeTime const when (
|
||||
RelativeTime::fromStartup() + secondsUntilDeadline);
|
||||
|
||||
m_manager->activate (*this, secondsUntilDeadline, when);
|
||||
Manager::instance().activate (*this, secondsUntilDeadline, when);
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#ifndef BEAST_MODULE_CORE_THREAD_DEADLINETIMER_H_INCLUDED
|
||||
#define BEAST_MODULE_CORE_THREAD_DEADLINETIMER_H_INCLUDED
|
||||
|
||||
#include <beast/module/core/memory/SharedSingleton.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Provides periodic or one time notifications at a specified time interval.
|
||||
@@ -108,7 +106,6 @@ private:
|
||||
class Manager;
|
||||
|
||||
Listener* const m_listener;
|
||||
SharedPtr <SharedSingleton <Manager> > m_manager;
|
||||
bool m_isActive;
|
||||
RelativeTime m_notificationTime;
|
||||
double m_secondsRecurring; // non zero if recurring
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace beast
|
||||
{
|
||||
#include <beast/utility/static_initializer.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
// Manages the list of hooks, and calls
|
||||
// whoever is in the list at exit time.
|
||||
@@ -33,7 +34,9 @@ public:
|
||||
|
||||
static inline Manager& get ()
|
||||
{
|
||||
return StaticObject <Manager>::get();
|
||||
static beast::static_initializer<
|
||||
Manager> instance;
|
||||
return *instance;
|
||||
}
|
||||
|
||||
void insert (Item& item)
|
||||
@@ -73,10 +76,6 @@ private:
|
||||
AtExitHook* const hook (item.hook ());
|
||||
hook->onExit ();
|
||||
}
|
||||
|
||||
// Now do the leak checking
|
||||
//
|
||||
LeakCheckedBase::checkForLeaks ();
|
||||
}
|
||||
|
||||
struct StaticDestructor
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
#define BEAST_MODULE_SQDB_API_SESSION_H_INCLUDED
|
||||
|
||||
#include <beast/smart_ptr/SharedPtr.h>
|
||||
#include <beast/module/core/memory/SharedSingleton.h>
|
||||
|
||||
namespace beast {
|
||||
namespace sqdb {
|
||||
@@ -137,8 +136,6 @@ private:
|
||||
Error hard_exec(std::string const& query);
|
||||
|
||||
private:
|
||||
class Sqlite3;
|
||||
SharedPtr <SharedSingleton <Sqlite3> > m_instance;
|
||||
bool m_bInTransaction;
|
||||
sqlite3* m_connection;
|
||||
String m_fileName;
|
||||
|
||||
@@ -62,26 +62,27 @@
|
||||
namespace beast {
|
||||
namespace sqdb {
|
||||
|
||||
class session::Sqlite3
|
||||
class Sqlite3Instance
|
||||
{
|
||||
public:
|
||||
Sqlite3()
|
||||
Sqlite3Instance()
|
||||
{
|
||||
assert (sqlite3_threadsafe() != 0);
|
||||
sqlite3_initialize();
|
||||
}
|
||||
|
||||
~Sqlite3()
|
||||
~Sqlite3Instance()
|
||||
{
|
||||
sqlite3_shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
Sqlite3Instance sqlite3_instance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
session::session()
|
||||
: prepare (this)
|
||||
, m_instance (SharedSingleton <Sqlite3>::getInstance ())
|
||||
, m_bInTransaction (false)
|
||||
, m_connection (nullptr)
|
||||
{
|
||||
@@ -89,7 +90,6 @@ session::session()
|
||||
|
||||
session::session(const session& deferredClone)
|
||||
: prepare (this)
|
||||
, m_instance (SharedSingleton <Sqlite3>::getInstance ())
|
||||
, m_bInTransaction (false)
|
||||
, m_connection (nullptr)
|
||||
, m_fileName (deferredClone.m_fileName)
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#ifndef BEAST_THREADS_THREAD_H_INCLUDED
|
||||
#define BEAST_THREADS_THREAD_H_INCLUDED
|
||||
|
||||
#include <beast/utility/LeakChecked.h>
|
||||
#include <beast/threads/RecursiveMutex.h>
|
||||
#include <beast/threads/WaitableEvent.h>
|
||||
|
||||
@@ -43,7 +42,7 @@ namespace beast {
|
||||
@see CriticalSection, WaitableEvent, Process, ThreadWithProgressWindow,
|
||||
MessageManagerLock
|
||||
*/
|
||||
class Thread : LeakChecked <Thread>
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace beast {
|
||||
method.
|
||||
*/
|
||||
class WaitableEvent
|
||||
//, LeakChecked <WaitableEvent> // VFALCO TODO Move LeakChecked to beast/
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
||||
@@ -1,181 +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_UTILITY_LEAKCHECKED_H_INCLUDED
|
||||
#define BEAST_UTILITY_LEAKCHECKED_H_INCLUDED
|
||||
|
||||
#include <beast/Config.h>
|
||||
#include <beast/intrusive/LockFreeStack.h>
|
||||
#include <beast/utility/StaticObject.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class LeakCheckedBase
|
||||
{
|
||||
public:
|
||||
static void checkForLeaks ();
|
||||
|
||||
protected:
|
||||
class LeakCounterBase : public LockFreeStack <LeakCounterBase>::Node
|
||||
{
|
||||
public:
|
||||
LeakCounterBase ();
|
||||
|
||||
virtual ~LeakCounterBase ()
|
||||
{
|
||||
}
|
||||
|
||||
inline int increment ()
|
||||
{
|
||||
return ++m_count;
|
||||
}
|
||||
|
||||
inline int decrement ()
|
||||
{
|
||||
return --m_count;
|
||||
}
|
||||
|
||||
virtual char const* getClassName () const = 0;
|
||||
|
||||
private:
|
||||
void checkForLeaks ();
|
||||
virtual void checkPureVirtual () const = 0;
|
||||
|
||||
class Singleton;
|
||||
friend class LeakCheckedBase;
|
||||
|
||||
std::atomic <int> m_count;
|
||||
};
|
||||
|
||||
static void reportDanglingPointer (char const* objectName);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Detects leaks at program exit.
|
||||
|
||||
To use this, derive your class from this template using CRTP (curiously
|
||||
recurring template pattern).
|
||||
*/
|
||||
template <class Object>
|
||||
class LeakChecked : private LeakCheckedBase
|
||||
{
|
||||
protected:
|
||||
LeakChecked () noexcept
|
||||
{
|
||||
getCounter ().increment ();
|
||||
}
|
||||
|
||||
LeakChecked (LeakChecked const&) noexcept
|
||||
{
|
||||
getCounter ().increment ();
|
||||
}
|
||||
|
||||
~LeakChecked ()
|
||||
{
|
||||
if (getCounter ().decrement () < 0)
|
||||
{
|
||||
reportDanglingPointer (getLeakCheckedName ());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Singleton that maintains the count of this object
|
||||
//
|
||||
class LeakCounter : public LeakCounterBase
|
||||
{
|
||||
public:
|
||||
LeakCounter () noexcept
|
||||
{
|
||||
}
|
||||
|
||||
char const* getClassName () const
|
||||
{
|
||||
return getLeakCheckedName ();
|
||||
}
|
||||
|
||||
void checkPureVirtual () const { }
|
||||
};
|
||||
|
||||
private:
|
||||
/* Due to a bug in Visual Studio 10 and earlier, the string returned by
|
||||
typeid().name() will appear to leak on exit. Therefore, we should
|
||||
only call this function when there's an actual leak, or else there
|
||||
will be spurious leak notices at exit.
|
||||
*/
|
||||
static const char* getLeakCheckedName ()
|
||||
{
|
||||
return typeid (Object).name ();
|
||||
}
|
||||
|
||||
// Retrieve the singleton for this object
|
||||
//
|
||||
static LeakCounter& getCounter () noexcept
|
||||
{
|
||||
return StaticObject <LeakCounter>::get();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
namespace disabled
|
||||
{
|
||||
|
||||
class LeakCheckedBase
|
||||
{
|
||||
public:
|
||||
static void checkForLeaks ()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class Object>
|
||||
class LeakChecked : public LeakCheckedBase
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Lift the appropriate implementation into our namespace
|
||||
//
|
||||
#if BEAST_CHECK_MEMORY_LEAKS
|
||||
using detail::LeakChecked;
|
||||
using detail::LeakCheckedBase;
|
||||
#else
|
||||
using detail::disabled::LeakChecked;
|
||||
using detail::disabled::LeakCheckedBase;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,124 +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_UTILITY_STATICOBJECT_H_INCLUDED
|
||||
#define BEAST_UTILITY_STATICOBJECT_H_INCLUDED
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace beast {
|
||||
|
||||
// Spec: N2914=09-0104
|
||||
//
|
||||
// [3.6.2] Initialization of non-local objects
|
||||
//
|
||||
// Objects with static storage duration (3.7.1) or thread storage
|
||||
// duration (3.7.2) shall be zero-initialized (8.5) before any
|
||||
// other initialization takes place.
|
||||
//
|
||||
|
||||
/** Wrapper to produce an object with static storage duration.
|
||||
|
||||
The object is constructed in a thread-safe fashion when the get function
|
||||
is first called. Note that the destructor for Object is never called. To
|
||||
invoke the destructor, use the AtExitHook facility (with caution).
|
||||
|
||||
The Tag parameter allows multiple instances of the same Object type, by
|
||||
using different tags.
|
||||
|
||||
Object must meet these requirements:
|
||||
DefaultConstructible
|
||||
|
||||
@see AtExitHook
|
||||
*/
|
||||
template <class Object, typename Tag = void>
|
||||
class StaticObject
|
||||
{
|
||||
public:
|
||||
static Object& get ()
|
||||
{
|
||||
StaticData& staticData (StaticData::get());
|
||||
|
||||
if (staticData.state.load () != initialized)
|
||||
{
|
||||
if (staticData.state.exchange (initializing) == uninitialized)
|
||||
{
|
||||
// Initialize the object.
|
||||
new (&staticData.object) Object;
|
||||
staticData.state = initialized;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t n = 0;
|
||||
|
||||
while (staticData.state.load () != initialized)
|
||||
{
|
||||
++n;
|
||||
|
||||
std::this_thread::yield ();
|
||||
|
||||
if (n > 10)
|
||||
{
|
||||
std::chrono::milliseconds duration (1);
|
||||
|
||||
if (n > 100)
|
||||
duration *= 10;
|
||||
|
||||
std::this_thread::sleep_for (duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (staticData.state.load () == initialized);
|
||||
return staticData.object;
|
||||
}
|
||||
|
||||
private:
|
||||
static int const uninitialized = 0;
|
||||
static int const initializing = 1;
|
||||
static int const initialized = 2;
|
||||
|
||||
// This structure gets zero-filled at static initialization time.
|
||||
// No constructors are called.
|
||||
//
|
||||
class StaticData
|
||||
{
|
||||
public:
|
||||
std::atomic <int> state;
|
||||
Object object;
|
||||
|
||||
static StaticData& get ()
|
||||
{
|
||||
static std::uint8_t storage [sizeof (StaticData)];
|
||||
return *(reinterpret_cast <StaticData*> (&storage [0]));
|
||||
}
|
||||
|
||||
StaticData() = delete;
|
||||
StaticData(StaticData const&) = delete;
|
||||
StaticData& operator= (StaticData const&) = delete;
|
||||
~StaticData() = delete;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <beast/utility/impl/Debug.cpp>
|
||||
#include <beast/utility/impl/Journal.cpp>
|
||||
#include <beast/utility/impl/LeakChecked.cpp>
|
||||
#include <beast/utility/impl/PropertyStream.cpp>
|
||||
|
||||
#include <beast/utility/tests/bassert.test.cpp>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/module/core/memory/SharedSingleton.h>
|
||||
#include <beast/utility/static_initializer.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -60,8 +60,8 @@ public:
|
||||
|
||||
Journal::Sink& Journal::getNullSink ()
|
||||
{
|
||||
return *SharedSingleton <NullJournalSink>::get (
|
||||
SingletonLifetime::neverDestroyed);
|
||||
static beast::static_initializer<NullJournalSink> sink;
|
||||
return *sink;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,102 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/utility/LeakChecked.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class LeakCheckedBase::LeakCounterBase::Singleton
|
||||
{
|
||||
public:
|
||||
void push_back (LeakCounterBase* counter)
|
||||
{
|
||||
m_list.push_front (counter);
|
||||
}
|
||||
|
||||
void checkForLeaks ()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
LeakCounterBase* const counter = m_list.pop_front ();
|
||||
|
||||
if (!counter)
|
||||
break;
|
||||
|
||||
counter->checkForLeaks ();
|
||||
}
|
||||
}
|
||||
|
||||
static Singleton& getInstance ()
|
||||
{
|
||||
static Singleton instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LeakCheckedBase;
|
||||
|
||||
LockFreeStack <LeakCounterBase> m_list;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LeakCheckedBase::LeakCounterBase::LeakCounterBase ()
|
||||
: m_count (0)
|
||||
{
|
||||
Singleton::getInstance ().push_back (this);
|
||||
}
|
||||
|
||||
void LeakCheckedBase::LeakCounterBase::checkForLeaks ()
|
||||
{
|
||||
// If there's a runtime error from this line, it means there's
|
||||
// an order of destruction problem between different translation units!
|
||||
//
|
||||
this->checkPureVirtual ();
|
||||
|
||||
int const count = m_count.load ();
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
outputDebugString ("Leaked objects: " + std::to_string (count) +
|
||||
" instances of " + getClassName ());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void LeakCheckedBase::reportDanglingPointer (char const* objectName)
|
||||
{
|
||||
outputDebugString (std::string ("Dangling pointer deletion: ") + objectName);
|
||||
bassertfalse;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void LeakCheckedBase::checkForLeaks ()
|
||||
{
|
||||
LeakCounterBase::Singleton::getInstance ().checkForLeaks ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user