Replace InstanceCounter with CountedObject

This commit is contained in:
Vinnie Falco
2013-06-17 17:45:33 -07:00
parent abce930b8b
commit 2abec05b5b
53 changed files with 321 additions and 334 deletions

View File

@@ -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"

View File

@@ -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"

View 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.
}
//------------------------------------------------------------------------------

View 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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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));

View File

@@ -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;