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:
parent
d173535c1c
commit
e93dca85c5
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
71
yateclass.h
71
yateclass.h
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue