固定大小的内存池

参考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

 

转载于:https://my.oschina.net/osbin/blog/349355

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值