当并发高时,可能存在多个连接公用一个锁,当有一个卡住时,会影响其他连接速度
可以按某种规则,比如用户uid,将不同用户拆分到不同的锁上面去,临界区共享数据也同样的规则做拆分
比如根据uid,%512的值,分配到不同的map下面
template<typename T1,typename T2>
class CMapGroup
{
typedef typename map<T1,T2>::iterator MAP_ITERATOR;
private:
pthread_rwlock_t rwLock;
pthread_rwlockattr_t rwLockAttr;
private:
map<T2 *, T1> m_objReverseAll;
CMapGroup(const CMapGroup & obj);
public:
short m_nGroupCount;
CThreadSafeMap<T1, T2> * m_pMaps;
CMapGroup()
{
pthread_rwlockattr_init(&rwLockAttr);
// set writing lock first
pthread_rwlockattr_setkind_np(&rwLockAttr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
if (pthread_rwlock_init(&rwLock, &rwLockAttr))
{
//SysLog("Init lock failed, errno: %d, line: %d", errno, __LINE__);
}
m_nGroupCount = 0;
m_pMaps = 0;
}
CMapGroup(const short nGroupCount)
{
m_nGroupCount = 0;
m_pMaps = 0;
Init(nGroupCount);
}
bool GetReadLock() const
{
if (pthread_rwlock_rdlock((pthread_rwlock_t *)&rwLock))
{
//SysLog("Acquire read lock failed, errno: %d, line: %d", errno, __LINE__);
return false;
}
return true;
}
bool GetWriteLock() const
{
if (pthread_rwlock_wrlock((pthread_rwlock_t *)&rwLock))
{
//SysLog("Acquire write lock failed, errno: %d, line: %d", errno, __LINE__);
return false;
}
return true;
}
bool ReleaseLock() const
{
if (pthread_rwlock_unlock((pthread_rwlock_t *)&rwLock))
{
//SysLog("Release lock failed, errno: %d, line: %d", errno, __LINE__);
return false;
}
return true;
}
unsigned int GetAllCount()
{
return m_objReverseAll.size();
}
void Init(const short nGroupCount)
{
if (m_pMaps)
{
delete [] m_pMaps;
}
m_nGroupCount = nGroupCount;
if (m_nGroupCount <= 0 || m_nGroupCount > 5000)
{
m_nGroupCount = 512;
}
m_pMaps = new CThreadSafeMap<T1, T2>[m_nGroupCount];
}
bool GetReadLock(const T1 & objKey)
{
return m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].GetReadLock();
}
bool GetWriteLock(const T1 & objKey)
{
return m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].GetWriteLock();
}
bool ReleaseLock(const T1 & objKey)
{
return m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].ReleaseLock();
}
map<T2 *,T1> * GetPlainMapChildReverse(const T1 & objKey)
{
return & m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].objChildReverse;
}
map<T2 *,T1> * GetPlainMapReverse(const T1 & objKey)
{
return & m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].objReverse;
}
map<T1,T2> * GetPlainMap(const T1 & objKey)
{
return & m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].obj;
}
T2 * Find(const T1 & objKey)
{
return m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].Find(objKey);
}
bool FindByValue(T2 * pValue)
{
bool bRet = false;
GetReadLock();
if (m_objReverseAll.find(pValue) != m_objReverseAll.end())
{
bRet = true;
}
ReleaseLock();
return bRet;
}
bool FindByValue(const T1 & objKey, T2 * pValue)
{
//return m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ].FindByValue(pValue);
bool bRet = false;
GetReadLock();
if (m_objReverseAll.find(pValue) != m_objReverseAll.end())
{
bRet = true;
}
ReleaseLock();
return bRet;
}
void Erase(const T1 & objKey, T2 * pObjValue1, T2 * pObjValue2_Child)
{
CThreadSafeMap<T1, T2> & mapFind = m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ];
mapFind.objChildReverse.erase(pObjValue2_Child);
mapFind.objReverse.erase(pObjValue1);
mapFind.obj.erase(objKey);
// private
GetWriteLock();
m_objReverseAll.erase(pObjValue2_Child);
m_objReverseAll.erase(pObjValue1);
ReleaseLock();
}
T2 * SetValue(const T1 & objKey, const T2 & objValue)
{
CThreadSafeMap<T1, T2> & m_mapFind = m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ];
//m_mapFind.GetWriteLock();
map<T1, T2> *pMap = m_mapFind.GetPlainMap();
map<T2 *,T1> *pMapReverse = m_mapFind.GetPlainMapReverse();
map<T2 *,T1> *pMapChildReverse = m_mapFind.GetPlainMapChildReverse();
(*pMap)[objKey] = objValue;
MAP_ITERATOR itr = pMap->find(objKey);
//SESSION *pSession = &itr->second;
//pSession->SetChild();
(*pMapReverse)[&itr->second] = objKey;
//(*pMapChildReverse)[pSession->pObjChild] = objKey;
//m_mapFind.ReleaseLock();
// private
GetWriteLock();
m_objReverseAll[&itr->second] = objKey;
ReleaseLock();
return &itr->second;
}
void SetValue_ChildReverse(const T1 & objKey, T2 * pObjValue_ChildReverse)
{
CThreadSafeMap<T1, T2> & m_mapFind = m_pMaps[( (unsigned long long)objKey % m_nGroupCount ) ];
map<T2 *,T1> *pMapChildReverse = m_mapFind.GetPlainMapChildReverse();
(*pMapChildReverse)[pObjValue_ChildReverse] = objKey;
// private
GetWriteLock();
m_objReverseAll[pObjValue_ChildReverse] = objKey;
ReleaseLock();
}
};
///
// end map group
///