Added MutexPool class implementing a fixed size array of mutexes. Replaced the global mutex protecting the RefObject counter changes with a mutex pool.

git-svn-id: http://voip.null.ro/svn/yate@3760 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2010-11-01 14:54:53 +00:00
parent d173535c1c
commit e93dca85c5
3 changed files with 106 additions and 16 deletions

View File

@ -601,6 +601,31 @@ bool Mutex::efficientTimedLock()
}
MutexPool::MutexPool(unsigned int len, bool recursive, const char* name)
: m_name(0), m_data(0), m_length(len ? len : 1)
{
if (TelEngine::null(name))
name = "Pool";
m_name = new String[m_length];
for (unsigned int i = 0; i < m_length; i++)
m_name[i] << name << "::" << (i + 1);
m_data = new Mutex*[m_length];
for (unsigned int i = 0; i < m_length; i++)
m_data[i] = new Mutex(recursive,m_name[i]);
}
MutexPool::~MutexPool()
{
if (m_data) {
for (unsigned int i = 0; i < m_length; i++)
delete m_data[i];
delete[] m_data;
}
if (m_name)
delete[] m_name;
}
Semaphore::Semaphore(unsigned int maxcount, const char* name)
: m_private(0)
{

View File

@ -81,6 +81,11 @@ namespace TelEngine {
#define OUT_BUFFER_SIZE 8192
// RefObject mutex pool array size
#ifndef REFOBJECT_MUTEX_COUNT
#define REFOBJECT_MUTEX_COUNT 47
#endif
static int s_debug = DebugWarn;
static int s_indent = 0;
static bool s_debugging = true;
@ -610,8 +615,12 @@ void GenObject::destruct()
delete this;
}
static MutexPool s_refMutex(REFOBJECT_MUTEX_COUNT,false,"RefObject");
static Mutex s_refmutex(false,"RefObject");
RefObject::RefObject()
: m_refcount(1), m_mutex(s_refMutex.mutex(this))
{
}
RefObject::~RefObject()
{
@ -640,20 +649,20 @@ bool RefObject::refInternal()
bool RefObject::ref()
{
Lock lock(s_refmutex);
Lock lock(m_mutex);
return refInternal();
}
bool RefObject::deref()
{
bool zeroCall = false;
s_refmutex.lock();
m_mutex->lock();
int i = m_refcount;
if (i > 0)
--m_refcount;
if (i == 1)
zeroCall = zeroRefsTest();
s_refmutex.unlock();
m_mutex->unlock();
if (zeroCall)
zeroRefs();
else if (i <= 0)
@ -674,11 +683,11 @@ bool RefObject::zeroRefsTest()
bool RefObject::resurrect()
{
s_refmutex.lock();
m_mutex->lock();
bool ret = (0 == m_refcount);
if (ret)
m_refcount = 1;
s_refmutex.unlock();
m_mutex->unlock();
return ret;
}
@ -686,11 +695,6 @@ void RefObject::destroyed()
{
}
Mutex& RefObject::refMutex()
{
return s_refmutex;
}
void RefPointerBase::assign(RefObject* oldptr, RefObject* newptr, void* pointer)
{
if (oldptr == newptr)

View File

@ -758,8 +758,7 @@ public:
* The constructor initializes the reference counter to 1!
* Use deref() to destruct the object when safe
*/
RefObject()
: m_refcount(1) { }
RefObject();
/**
* Destructor.
@ -804,10 +803,11 @@ public:
virtual void destruct();
/**
* Retrieve the mutex that protects ref() and deref() for all objects
* @return Reference to the global mutex used for all counter operations
* Retrieve the mutex that protects ref() and deref() for this object
* @return Reference to the mutex used for counter operations
*/
static Mutex& refMutex();
inline Mutex& refMutex()
{ return *m_mutex; }
protected:
/**
@ -850,6 +850,7 @@ protected:
private:
int m_refcount;
Mutex* m_mutex;
};
/**
@ -4320,6 +4321,66 @@ private:
MutexPrivate* m_private;
};
/**
* This class holds a Mutex array. Mutexes can be retrieved based on object pointers.
* A mutex pool can be used to associate a smaller set of Mutex objects with a much
* larger set of objects needing lock.
* @short A Mutex pool
*/
class MutexPool
{
public:
/**
* Build the mutex pool
* @param len The number of mutex objects to build. The length should be an
* odd number to obtain an optimal distribution of pointer based mutexes
* (usually pointers are aligned at even addresses): some mutexes might never
* get used if the length is an even number
* @param recursive True if the mutex has to be recursive (reentrant),
* false for a normal fast mutex
* @param name Static name of the mutex (for debugging purpose only)
*/
MutexPool(unsigned int len = 13, bool recursive = false, const char* name = 0);
/**
* Destructor. Release data
*/
~MutexPool();
/**
* Build an index from object pointer (pointer value modulo array length).
* Always cast the pointer to the same type when calling this method to
* make sure the same index is returned for a given object
* @param ptr The pointer to object
* @return Valid array index
*/
inline unsigned int index(void* ptr) const
{ return ((unsigned int)ptr) % m_length; }
/**
* Retrieve the mutex associated with a given pointer.
* Always cast the pointer to the same type when calling this method to
* make sure the same mutex is returned for a given object
* @param ptr The pointer to object
* @return Valid Mutex pointer
*/
inline Mutex* mutex(void* ptr) const
{ return m_data[index(ptr)]; }
/**
* Retrieve the mutex at a given index modulo array length
* @param idx The index
* @return Valid Mutex pointer
*/
inline Mutex* mutex(unsigned int idx) const
{ return m_data[idx % m_length]; }
private:
String* m_name; // Mutex names
Mutex** m_data; // The array
unsigned int m_length; // Array length
};
/**
* A semaphore object for synchronizing threads, can also be used as a token bucket
* @short Semaphore implementation