参考LOKI内存池实现。当定义了USE_NO_LOCK宏时,编译成无锁版本。
// defs.h
#ifndef _DEFS_H_
#define _DEFS_H_
typedef char int8 ;
typedef unsigned char uint8 ;
typedef uint8 byte ;
typedef short int16 ;
typedef unsigned short uint16 ;
typedef int int32 ;
typedef unsigned int uint32 ;
#ifdef _MSC_VER
typedef __int64 int64 ;
typedef unsigned __int64 uint64 ;
#ifdef _WIN32
typedef uint32 uaddr ;
#else
typedef uint64 uaddr ;
#endif
#define STDCALL __stdcall
#else
typedef long long int64 ;
typedef unsigned long long uint64 ;
#if __SIZEOF_POINTER__ == 4
typedef uint32 uaddr ;
#elif __SIZEOF_POINTER__ == 8
typedef uint64 uaddr ;
#endif
#define STDCALL __attribute__((stdcall))
#endif
#ifdef USE_NO_LOCK
#define MEM_POOL_NO_LOCK
#define TASK_SCHEDULE_NO_LOCK
#define IO_BUFFER_NO_LOCK
#endif
#endif //_DEFS_H_
// atom.h 原子操作
#ifndef _ATOM_H_
#define _ATOM_H_
#include "defs.h"
#ifdef _MSC_VER
#include <windows.h>
#elif defined(__GNUC__)
#if __GNUC__<4 || (__GNUC__==4 && __GNUC_MINOR__<1)
#error GCC version must be greater or equal than 4.1.2
#endif
//#include <sched.h>
#else
#error Currently only windows and linux os are supported
#endif
//自增,返回新值
inline uint32 AtomSelfAdd(void *var)
{
#ifdef _MSC_VER
return InterlockedIncrement((long *)var); // NOLINT
#else
return __sync_add_and_fetch((uint32 *)var, 1); // NOLINT
#endif
}
//自减,返回新值
inline uint32 AtomSelfDec(void *var)
{
#ifdef _MSC_VER
return InterlockedDecrement((long *)var); // NOLINT
#else
return __sync_add_and_fetch((uint32 *)var, -1); // NOLINT
#endif
}
//加一个值,返回旧值
inline uint32 AtomAdd(void *var, const uint32 value)
{
#ifdef _MSC_VER
return InterlockedExchangeAdd((long *)var, value); // NOLINT
#else
return __sync_fetch_and_add((uint32 *)var, value); // NOLINT
#endif
}
//减一个值,返回旧值
inline uint32 AtomDec(void *var, int32 value)
{
value = value * -1;
#ifdef _MSC_VER
return InterlockedExchangeAdd((long *)var, value); // NOLINT
#else
return __sync_fetch_and_add((uint32 *)var, value); // NOLINT
#endif
}
//赋值,windows下返回新值,linux下返回旧值
inline uint32 AtomSet(void *var, const uint32 value)
{
#ifdef _MSC_VER
::InterlockedExchange((long *)var, (long)value); // NOLINT
#else
__sync_lock_test_and_set((uint32 *)var, value); // NOLINT
#endif
return value;
}
//取值
inline uint32 AtomGet(void *var)
{
#ifdef _MSC_VER
return InterlockedExchangeAdd((long *)var, 0); // NOLINT
#else
return __sync_fetch_and_add((uint32 *)var, 0); // NOLINT
#endif
}
//cas 返回旧值
inline uint32 AtomCmpAndSet(void *var, uint32 uiCmp, uint32 uiSet)
{
#ifdef _MSC_VER
return InterlockedCompareExchange((long *)var, (long)uiSet, (long)uiCmp) ;
#else
return __sync_val_compare_and_swap((uint32 *)var, uiCmp, uiSet) ;
#endif
}
//cas 返回旧值
inline void* AtomCmpAndSetPointer(void **pOri, void *pCmp, void *pSet)
{
#ifdef _MSC_VER
return InterlockedCompareExchangePointer(pOri, pSet, pCmp) ;
#else
return __sync_val_compare_and_swap(pOri, pCmp, pSet) ;
#endif
}
//cas 返回bool值
inline bool AtomBoolCmpAndSet(void *var, uint32 uiCmp, uint32 uiSet)
{
#ifdef _MSC_VER
return InterlockedCompareExchange((long *)var, (long)uiSet, (long)uiCmp) == (long)uiCmp ;
#else
return __sync_bool_compare_and_swap((uint32 *)var, uiCmp, uiSet) ;
#endif
}
//cas 返回bool值
inline bool AtomBoolCmpAndSetPointer(void **pOri, void *pCmp, void *pSet)
{
#ifdef _MSC_VER
return InterlockedCompareExchangePointer(pOri, pSet, pCmp) == pCmp ;
#else
return __sync_bool_compare_and_swap(pOri, pCmp, pSet) ;
#endif
}
#endif //_ATOM_H_
// Sync.h
#ifndef _MDL_SYNC_H_
#define _MDL_SYNC_H_
#include "defs.h"
#include "atom.h"
#define _SYNC_NO_LOCK_ //使用无锁
#ifdef _SYNC_NO_LOCK_
typedef volatile uint32 SYNCOBJ;
#ifdef _WIN_VER_
#include <Windows.h>
#if(_WIN32_WINNT >= 0x0400)
#define Sync_Yield() SwitchToThread()
#else
#define Sync_Yield() Sleep(0)
#endif
#else
#include <sched.h>
#define Sync_Yield() sched_yield()
#endif
#define Sync_Init(pObj) *(pObj) = 0
#define Sync_Destroy(pObj) *(pObj) = 0
#define Sync_Lock(pObj) while(0 != *(pObj) || 1 != AtomSelfAdd((void *)(pObj))){Sync_Yield();}
#define Sync_Unlock(pObj) AtomSet((void *)(pObj), 0)
#else
#ifdef _WIN_VER_
#include <Windows.h>
typedef CRITICAL_SECTION SYNCOBJ;
#define Sync_Init(pObj) InitializeCriticalSection(pObj)
#define Sync_Destroy(pObj) DeleteCriticalSection(pObj)
#define Sync_Lock(pObj) EnterCriticalSection(pObj)
#define Sync_Unlock(pObj) LeaveCriticalSection(pObj)
#else
#include <pthread.h>
typedef pthread_mutex_t SYNCOBJ;
#define Sync_Init(pObj) pthread_mutex_init(pObj, NULL)
#define Sync_Destroy(pObj) pthread_mutex_destroy(pObj)
#define Sync_Lock(pObj) pthread_mutex_lock(pObj)
#define Sync_Unlock(pObj) pthread_mutex_unlock(pObj)
#endif
#endif
namespace mdl
{
class Sync
{
public:
Sync()
{
Sync_Init(&m_syncObj);
}
~Sync()
{
Sync_Destroy(&m_syncObj);
}
void Lock()
{
Sync_Lock(&m_syncObj);
}
void Unlock()
{
Sync_Unlock(&m_syncObj);
}
private:
Sync(const Sync &);
Sync& operator=(const Sync &);
private:
SYNCOBJ m_syncObj;
};
class AutoSync
{
public:
AutoSync(Sync *pSync) : m_pSync(pSync), m_bLocked(true)
{
m_pSync->Lock();
}
~AutoSync()
{
Unlock();
}
void Unlock()
{
if(m_bLocked)
{
m_pSync->Unlock();
m_bLocked = false;
}
}
private:
AutoSync(const AutoSync &);
AutoSync& operator=(const AutoSync &);
private:
Sync *m_pSync;
bool m_bLocked;
};
} // namespace mdl
#endif //_MDL_SYNC_H_
// MemPool.h
#ifndef _MDL_MEM_POOL_H_
#define _MDL_MEM_POOL_H_
#include "defs.h"
#include "atom.h"
#include "Sync.h"
namespace mdl
{
class MemBlock
{
public:
MemBlock();
~MemBlock();
byte *Allocator(uint32 uiSize, uint32 uiCount);
private:
byte *AllocBuf(uint32 uiSize, uint32 uiCount);
MemBlock *m_pNextBlock;
byte *m_pBuf; //预先申请的内存块
};
class MemPool
{
public:
MemPool(uint32 uiSize, uint32 uiCount = 512);
virtual ~MemPool();
void *Alloc();
void Free(void *pMem);
uint32 GetPerMemSize() { return m_uiSize; }
uint32 GetPerBlockCount() { return m_uiCount; }
uint32 GetUsedCount() { return m_uiUsed; }
uint32 GetFreeCount() { return m_uiFree; }
protected:
MemBlock m_memBlock;
byte *m_pNextFreeMem; //下一个可分配的内存地址
uint32 m_uiSize; //分配出去的每个内存大小
uint32 m_uiCount; //数量。m_pBufList[i]指向内存块(大小:m_uiSize * m_uiCount)
volatile uint32 m_uiUsed; //使用数
volatile uint32 m_uiFree; //空闲数
Sync m_lock; //
private:
byte *AllocBlock(uint32 uiSize, uint32 uiCount);
MemPool(const MemPool &);
MemPool& operator=(const MemPool &);
};
} // namespace mdl
#endif //_MDL_MEM_POOL_H_
// MemPool.cpp
#include <stddef.h>
#include <new>
#include "MemPool.h"
namespace mdl
{
MemBlock::MemBlock() : m_pNextBlock(NULL), m_pBuf(NULL)
{
}
MemBlock::~MemBlock()
{
if(NULL != m_pBuf)
delete [] m_pBuf;
if(NULL != m_pNextBlock)
delete m_pNextBlock;
}
byte* MemBlock::Allocator(uint32 uiSize, uint32 uiCount)
{
MemBlock *p = new (std::nothrow) MemBlock;
if(NULL != p && NULL != p->AllocBuf(uiSize, uiCount))
{
p->m_pNextBlock = m_pNextBlock;
m_pNextBlock = p;
return p->m_pBuf;
}
else
{
if(NULL != p)
delete p;
return NULL;
}
}
byte* MemBlock::AllocBuf(uint32 uiSize, uint32 uiCount)
{
uint32 ui;
m_pBuf = new (std::nothrow) byte[uiSize * uiCount];
//m_pNextBlock = NULL;
if(NULL != m_pBuf)
{
for(ui=0; ui<uiCount-1; ui++)
*(uaddr *)((uaddr)m_pBuf + uiSize * ui) = (uaddr)m_pBuf + uiSize * (ui + 1);
*(uaddr *)((uaddr)m_pBuf + uiSize * ui) = 0;
}
return m_pBuf;
}
//
MemPool::MemPool(uint32 uiSize, uint32 uiCount /* = 512 */)
{
m_uiSize = (uiSize + sizeof(void *)-1) & ~(sizeof(void *) - 1);
if(m_uiSize < sizeof(void *))
m_uiSize = sizeof(void *);
m_uiCount = uiCount;
m_uiUsed = 0;
m_uiFree = uiCount;
m_pNextFreeMem = NULL;
}
MemPool::~MemPool()
{
//
}
void* MemPool::Alloc()
{
byte *p = NULL;
m_lock.Lock();
if(m_pNextFreeMem != NULL || (m_pNextFreeMem = AllocBlock(m_uiSize, m_uiCount)) != NULL)
{
p = m_pNextFreeMem;
m_pNextFreeMem = (byte *)*(uaddr *)p;
m_uiFree--;
m_uiUsed++;
}
m_lock.Unlock();
return p;
}
void MemPool::Free(void *pMem)
{
if(NULL != pMem)
{
m_lock.Lock();
*(uaddr *)pMem = (uaddr)m_pNextFreeMem;
m_pNextFreeMem = (byte *)pMem;
m_uiFree++;
m_uiUsed--;
m_lock.Unlock();
}
}
byte* MemPool::AllocBlock(uint32 uiSize, uint32 uiCount)
{
byte *p = m_memBlock.Allocator(m_uiSize, uiCount);
if(p != NULL)
m_uiFree += m_uiCount;
return p;
}
} // namespace mdl