mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Replace InstanceCounter with CountedObject
This commit is contained in:
@@ -57,8 +57,8 @@
|
||||
#include "utility/ripple_Log.cpp"
|
||||
|
||||
#include "utility/ripple_ByteOrder.cpp"
|
||||
#include "utility/ripple_CountedObject.cpp"
|
||||
#include "utility/ripple_DiffieHellmanUtil.cpp"
|
||||
#include "utility/ripple_InstanceCounter.cpp"
|
||||
#include "utility/ripple_StringUtilities.cpp"
|
||||
#include "utility/ripple_Sustain.cpp"
|
||||
#include "utility/ripple_ThreadName.cpp"
|
||||
|
||||
@@ -40,49 +40,18 @@
|
||||
#error Boost 1.47 or later is required
|
||||
#endif
|
||||
|
||||
// Log
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
// Forward declaration
|
||||
/*
|
||||
namespace boost {
|
||||
namespace filesystem {
|
||||
class path;
|
||||
}
|
||||
}
|
||||
*/
|
||||
#include <boost/filesystem.hpp> // VFALCO TODO try to eliminate thie dependency
|
||||
|
||||
|
||||
|
||||
// KeyCache
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
// RangeSet
|
||||
#include <boost/foreach.hpp>
|
||||
//#include <boost/icl/interval_set.hpp> // oof this one is ugly
|
||||
|
||||
// InstanceCounter
|
||||
//#include <string>
|
||||
//#include <vector>
|
||||
//#include <boost/thread/mutex.hpp>
|
||||
|
||||
// TaggedCache
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
// RippleTime
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
// ScopedLock
|
||||
//#include <boost/thread/recursive_mutex.hpp>
|
||||
//#include <boost/shared_ptr.hpp>
|
||||
//#include <boost/make_shared.hpp>
|
||||
//#include <boost/ref.hpp>
|
||||
|
||||
// ByteOrder
|
||||
#ifdef WIN32
|
||||
// (nothing)
|
||||
@@ -112,6 +81,7 @@ namespace boost {
|
||||
|
||||
#include "BeastConfig.h"
|
||||
#include "modules/beast_core/beast_core.h"
|
||||
#include "modules/beast_basics/beast_basics.h"
|
||||
|
||||
#include "../ripple_json/ripple_json.h"
|
||||
|
||||
@@ -120,8 +90,8 @@ namespace boost {
|
||||
|
||||
#include "types/ripple_BasicTypes.h"
|
||||
#include "utility/ripple_ByteOrder.h"
|
||||
#include "utility/ripple_CountedObject.h"
|
||||
#include "utility/ripple_DiffieHellmanUtil.h"
|
||||
#include "utility/ripple_InstanceCounter.h"
|
||||
#include "utility/ripple_PlatformMacros.h"
|
||||
#include "utility/ripple_RandomNumbers.h"
|
||||
#include "utility/ripple_ScopedLock.h"
|
||||
|
||||
78
modules/ripple_basics/utility/ripple_CountedObject.cpp
Normal file
78
modules/ripple_basics/utility/ripple_CountedObject.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
CountedObjects& CountedObjects::getInstance ()
|
||||
{
|
||||
static CountedObjects instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
CountedObjects::CountedObjects ()
|
||||
{
|
||||
}
|
||||
|
||||
CountedObjects::~CountedObjects ()
|
||||
{
|
||||
}
|
||||
|
||||
CountedObjects::List CountedObjects::getCounts (int minimumThreshold) const
|
||||
{
|
||||
List counts;
|
||||
|
||||
// When other operations are concurrent, the count
|
||||
// might be temporarily less than the actual count.
|
||||
int const count = m_count.get ();
|
||||
|
||||
counts.reserve (count);
|
||||
|
||||
CounterBase* counter = m_head.get ();
|
||||
|
||||
while (counter != nullptr)
|
||||
{
|
||||
if (counter->getCount () >= minimumThreshold)
|
||||
{
|
||||
Entry entry;
|
||||
|
||||
entry.first = counter->getName ();
|
||||
entry.second = counter->getCount ();
|
||||
|
||||
counts.push_back (entry);
|
||||
}
|
||||
|
||||
counter = counter->getNext ();
|
||||
}
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
CountedObjects::CounterBase::CounterBase ()
|
||||
{
|
||||
// Insert ourselves at the front of the lock-free linked list
|
||||
|
||||
CountedObjects& instance = CountedObjects::getInstance ();
|
||||
CounterBase* head;
|
||||
|
||||
do
|
||||
{
|
||||
head = instance.m_head.get ();
|
||||
m_next = head;
|
||||
}
|
||||
while (! instance.m_head.compareAndSetBool (this, head));
|
||||
|
||||
++instance.m_count;
|
||||
}
|
||||
|
||||
CountedObjects::CounterBase::~CounterBase ()
|
||||
{
|
||||
// VFALCO NOTE If the counters are destroyed before the singleton,
|
||||
// undefined behavior will result if the singleton's member
|
||||
// functions are called.
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
150
modules/ripple_basics/utility/ripple_CountedObject.h
Normal file
150
modules/ripple_basics/utility/ripple_CountedObject.h
Normal file
@@ -0,0 +1,150 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_COUNTEDOBJECT_RIPPLEHEADER
|
||||
#define RIPPLE_COUNTEDOBJECT_RIPPLEHEADER
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Manages all counted object types.
|
||||
*/
|
||||
class CountedObjects
|
||||
{
|
||||
public:
|
||||
static CountedObjects& getInstance ();
|
||||
|
||||
typedef std::pair <std::string, int> Entry;
|
||||
typedef std::vector <Entry> List;
|
||||
|
||||
List getCounts (int minimumThreshold) const;
|
||||
|
||||
public:
|
||||
/** Implementation for @ref CountedObject.
|
||||
|
||||
@internal
|
||||
*/
|
||||
class CounterBase
|
||||
{
|
||||
public:
|
||||
CounterBase ();
|
||||
|
||||
virtual ~CounterBase ();
|
||||
|
||||
inline int increment () noexcept
|
||||
{
|
||||
return ++m_count;
|
||||
}
|
||||
|
||||
inline int decrement () noexcept
|
||||
{
|
||||
return --m_count;
|
||||
}
|
||||
|
||||
inline int getCount () const noexcept
|
||||
{
|
||||
return m_count.get ();
|
||||
}
|
||||
|
||||
inline CounterBase* getNext () const noexcept
|
||||
{
|
||||
return m_next;
|
||||
}
|
||||
|
||||
virtual char const* getName () const = 0;
|
||||
|
||||
private:
|
||||
virtual void checkPureVirtual () const = 0;
|
||||
|
||||
protected:
|
||||
beast::Atomic <int> m_count;
|
||||
CounterBase* m_next;
|
||||
};
|
||||
|
||||
private:
|
||||
CountedObjects ();
|
||||
|
||||
~CountedObjects ();
|
||||
|
||||
private:
|
||||
beast::Atomic <int> m_count;
|
||||
beast::Atomic <CounterBase*> m_head;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Tracks the number of instances of an object.
|
||||
|
||||
Derived classes have their instances counted automatically. This is used
|
||||
for reporting purposes.
|
||||
|
||||
@ingroup ripple_basics
|
||||
*/
|
||||
template <class Object>
|
||||
class CountedObject
|
||||
{
|
||||
public:
|
||||
CountedObject ()
|
||||
{
|
||||
getCounter ().increment ();
|
||||
}
|
||||
|
||||
CountedObject (CountedObject const&)
|
||||
{
|
||||
getCounter ().increment ();
|
||||
}
|
||||
|
||||
~CountedObject ()
|
||||
{
|
||||
getCounter ().decrement ();
|
||||
}
|
||||
|
||||
private:
|
||||
class Counter : public CountedObjects::CounterBase
|
||||
{
|
||||
public:
|
||||
Counter () noexcept { }
|
||||
|
||||
char const* getName () const noexcept
|
||||
{
|
||||
return getClassName ();
|
||||
}
|
||||
|
||||
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 char const* getClassName () noexcept
|
||||
{
|
||||
return typeid (Object).name ();
|
||||
}
|
||||
|
||||
static Counter& getCounter () noexcept
|
||||
{
|
||||
// VFALCO TODO Research the thread safety of static initializers
|
||||
// on all supported platforms
|
||||
static Counter counter;
|
||||
return counter;
|
||||
|
||||
/*
|
||||
static Counter* volatile s_instance;
|
||||
static beast::Static::Initializer s_initializer;
|
||||
if (s_initializer.begin ())
|
||||
{
|
||||
static char s_storage [sizeof (Counter)];
|
||||
s_instance = new (s_storage) Counter;
|
||||
s_initializer.end ();
|
||||
}
|
||||
return *s_instance;
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,23 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
InstanceType* InstanceType::sHeadInstance = NULL;
|
||||
bool InstanceType::sMultiThreaded = false;
|
||||
|
||||
std::vector<InstanceType::InstanceCount> InstanceType::getInstanceCounts (int min)
|
||||
{
|
||||
std::vector<InstanceCount> ret;
|
||||
|
||||
for (InstanceType* i = sHeadInstance; i != NULL; i = i->mNextInstance)
|
||||
{
|
||||
int c = i->getCount ();
|
||||
|
||||
if (c >= min)
|
||||
ret.push_back (InstanceCount (i->getName (), c));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_INSTANCECOUNTER_H
|
||||
#define RIPPLE_INSTANCECOUNTER_H
|
||||
|
||||
// VFALCO TODO Clean this up, remove the macros, replace
|
||||
// with a robust leak checker when we have atomics.
|
||||
//
|
||||
|
||||
// VFALCO TODO swap these. Declaration means header, definition means .cpp!!!
|
||||
#define DEFINE_INSTANCE(x) \
|
||||
extern InstanceType IT_##x; \
|
||||
class Instance_##x : private Instance \
|
||||
{ \
|
||||
protected: \
|
||||
Instance_##x() : Instance(IT_##x) { ; } \
|
||||
Instance_##x(const Instance_##x &) : \
|
||||
Instance(IT_##x) { ; } \
|
||||
Instance_##x& operator=(const Instance_##x&) \
|
||||
{ return *this; } \
|
||||
}
|
||||
|
||||
#define DECLARE_INSTANCE(x) \
|
||||
InstanceType IT_##x(#x);
|
||||
|
||||
#define IS_INSTANCE(x) Instance_##x
|
||||
|
||||
// VFALCO NOTE that this is just a glorified leak checker with an awkward API
|
||||
class InstanceType
|
||||
{
|
||||
protected:
|
||||
int mInstances;
|
||||
std::string mName;
|
||||
boost::mutex mLock;
|
||||
|
||||
InstanceType* mNextInstance;
|
||||
static InstanceType* sHeadInstance;
|
||||
static bool sMultiThreaded;
|
||||
|
||||
public:
|
||||
typedef std::pair<std::string, int> InstanceCount;
|
||||
|
||||
explicit InstanceType (const char* n) : mInstances (0), mName (n)
|
||||
{
|
||||
mNextInstance = sHeadInstance;
|
||||
sHeadInstance = this;
|
||||
}
|
||||
|
||||
static void multiThread ()
|
||||
{
|
||||
// We can support global objects and multi-threaded code, but not both
|
||||
// at the same time. Switch to multi-threaded.
|
||||
sMultiThreaded = true;
|
||||
}
|
||||
|
||||
static void shutdown ()
|
||||
{
|
||||
sMultiThreaded = false;
|
||||
}
|
||||
|
||||
static bool isMultiThread ()
|
||||
{
|
||||
return sMultiThreaded;
|
||||
}
|
||||
|
||||
void addInstance ()
|
||||
{
|
||||
if (sMultiThreaded)
|
||||
{
|
||||
// VFALCO NOTE This will go away with atomics
|
||||
mLock.lock ();
|
||||
++mInstances;
|
||||
mLock.unlock ();
|
||||
}
|
||||
else ++mInstances;
|
||||
}
|
||||
void decInstance ()
|
||||
{
|
||||
if (sMultiThreaded)
|
||||
{
|
||||
mLock.lock ();
|
||||
--mInstances;
|
||||
mLock.unlock ();
|
||||
}
|
||||
else --mInstances;
|
||||
}
|
||||
int getCount ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mInstances;
|
||||
}
|
||||
const std::string& getName ()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
static std::vector<InstanceCount> getInstanceCounts (int min = 1);
|
||||
};
|
||||
|
||||
class Instance
|
||||
{
|
||||
protected:
|
||||
static bool running;
|
||||
InstanceType& mType;
|
||||
|
||||
public:
|
||||
Instance (InstanceType& t) : mType (t)
|
||||
{
|
||||
mType.addInstance ();
|
||||
}
|
||||
~Instance ()
|
||||
{
|
||||
if (running) mType.decInstance ();
|
||||
}
|
||||
static void shutdown ()
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef RIPPLE_INTEGERTYPES_H
|
||||
#define RIPPLE_INTEGERTYPES_H
|
||||
|
||||
// VFALCO TODO Get rid of these and use the types from beast instead.
|
||||
// VFALCO TODO determine if Borland C is supported
|
||||
#if defined (_MSC_VER) /*|| defined(__BORLANDC__)*/
|
||||
typedef __int64 int64;
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
SETUP_LOG (STObject)
|
||||
|
||||
DECLARE_INSTANCE (SerializedObject);
|
||||
DECLARE_INSTANCE (SerializedArray);
|
||||
|
||||
UPTR_T<SerializedType> STObject::makeDefaultObject (SerializedTypeID id, SField::ref name)
|
||||
{
|
||||
assert ((id == STI_NOTPRESENT) || (id == name.fieldType));
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
#ifndef RIPPLE_SERIALIZEDOBJECT_H
|
||||
#define RIPPLE_SERIALIZEDOBJECT_H
|
||||
|
||||
DEFINE_INSTANCE (SerializedObject);
|
||||
DEFINE_INSTANCE (SerializedArray);
|
||||
|
||||
class STObject : public SerializedType, private IS_INSTANCE (SerializedObject)
|
||||
class STObject
|
||||
: public SerializedType
|
||||
, public CountedObject <STObject>
|
||||
{
|
||||
public:
|
||||
STObject () : mType (NULL)
|
||||
@@ -298,7 +297,9 @@ template<> struct range_const_iterator<STObject>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class STArray : public SerializedType, private IS_INSTANCE (SerializedArray)
|
||||
class STArray
|
||||
: public SerializedType
|
||||
, public CountedObject <STArray>
|
||||
{
|
||||
public:
|
||||
typedef boost::ptr_vector<STObject> vector;
|
||||
|
||||
Reference in New Issue
Block a user