实现内存池MemoryPool(加了互斥锁的内存池实现:pthread_mutex_t + m_memory_pool)

在前面一篇用线程私有数据TSD实现了线程间无竞争的内存池,因为每个线程都会有自己的私有key对应的私有线程池,所以每个线程之间使用的内存池不会有任何竞争。

文章地址:实现一个线程安全的内存池(使用线程私有数据机制TSD来实现)


本篇文章使用公共内存池和系统锁pthread_mutex_t进行内存池的同步,所以本篇实现的内存池因为使用了公共内存池和锁,所以当有多个线程同时申请内存时,会产生锁操作,所以比起上篇实现的线程安全的内存池这是一个缺点,请注意。


//MemoryPool.h
#ifndef __BLUESKY_MEMORYPOOL_H__
#define __BLUESKY_MEMORYPOOL_H__

///编译时请执行 $g++ -c ./MemoryPool.cpp -o mp.o -lpthread
///使用pthread_once系列函数时,编译时要添加-lpthread选项!
#include 
#include //for pthread_mutex系列函数
#include 	//for glibc malloc/free
#include  //for offsetof()
#include 	//for uint32_t and so on.
#include  //for memcpy

namespace BlueSky {

//< memory node for buf
struct node {
	int32_t 	index;
	uint32_t	mem_size;
	struct node*	next;
	char buf[0];
};

//< memory node list head for same SIZE_TYPE's node
struct head {
	uint16_t	nodes_cap;
	uint16_t	nodes_size;
	uint32_t	mem_size;
	struct node*	head;
	struct node*	tail;
};

class CMemoryPool
{
private:
	CMemoryPool(){};
	~CMemoryPool(){};
	
public:
	static void CreateMemoryPool();
	static void DestroyMemoryPool();
	static void* Malloc(uint32_t);
	static void Free(void* ptr);
	static void Init();
private:
	//< get size's hash value as memory-list-array's index
	static inline int get_index(uint32_t size);

private:
	#define SIZE_TYPE_NUM 46
	static struct head		m_memory_template[SIZE_TYPE_NUM];
	static struct head*		m_memory_pool;
	static pthread_mutex_t	m_pool_mutex;
};//CMemoryPool

}//namespace BlueSky

#endif

//MemoryPool.cpp
#include "MemoryPool.h"
namespace BlueSky{

struct head 	CMemoryPool::m_memory_template[SIZE_TYPE_NUM];
struct head*	CMemoryPool::m_memory_pool;
pthread_mutex_t	CMemoryPool::m_pool_mutex;

#define MUTEX_LOCK \
	do { \
		pthread_mutex_lock(&m_pool_mutex); \
	}while(0);
	
#define MUTEX_UNLOCK \
	do {\
		pthread_mutex_unlock(&m_pool_mutex); \
	}while(0);

void CMemoryPool::Init()
{
	m_memory_pool = NULL;
}

void CMemoryPool::CreateMemoryPool()
{
	if (m_memory_pool == NULL)
	{
		m_memory_pool = new struct head[SIZE_TYPE_NUM];
		memcpy (m_memory_pool, m_memory_template, sizeof (struct head) * SIZE_TYPE_NUM);
	}
}

void CMemoryPool::DestroyMemoryPool()
{
	if (m_memory_pool != NULL)
	{
		free(m_memory_pool);
		m_memory_pool = NULL;
	}
}

void* CMemoryPool::Malloc(uint32_t size)
{
	struct node* ret  = NULL;
	/// 情况1:申请超过256K的buf时,直接使用glibc的malloc来申请
	if (size > 256 * 1024 || NULL == m_memory_pool)
	{
		uint32_t len = sizeof(struct node) + size;
		ret = (struct node*)malloc( len );
		ret->index = -1;//表示free时直接free,不放到memory_pool中
		return ret->buf;
	}
	int index = get_index( size );
	MUTEX_LOCK;
	ret = m_memory_pool[index].head;
	/// 情况2:从pool中取buf,有空闲buf的node,取出此node并将其buf返回给用户
	if (ret)
	{
		m_memory_pool[index].head = ret->next;
		ret->next = NULL;
		m_memory_pool[index].nodes_size -= 1;
		MUTEX_UNLOCK;
		return ret->buf;
	}
	MUTEX_UNLOCK;
	/// 情况3:从pool中取buf,无空闲buf的ndoe, malloc一个node给用户
	/// 用户free此buf时再将其放入到pool中
	uint32_t len = sizeof(struct node) + m_memory_pool[index].mem_size;
	ret = (struct node*)malloc( len );
	ret->index = index;
	ret->mem_size = m_memory_pool[index].mem_size;
	ret->next = NULL;
	return ret->buf;
}
void CMemoryPool::Free( void* ptr)
{
	struct node* pnode = (struct node*)((char*)ptr - offsetof(struct node, buf));
	int index = pnode->index;
	if (index == -1) {
		free(pnode);
		return ;
	}
	MUTEX_LOCK;
	bool full = m_memory_pool[index].nodes_size == m_memory_pool[index].nodes_cap;
	if (full) {
		MUTEX_UNLOCK;
		free(pnode);
		return ;
	}
	struct head list = m_memory_pool[index];
	if (list.head == NULL) {
		list.head = pnode;
		list.tail = pnode;
	} 
	else {
		list.tail->next = pnode;
		list.tail = pnode;
	}
	list.nodes_size += 1;
	MUTEX_UNLOCK;
	return;
}
//< get size's hash value as memory-list-array's index
inline int CMemoryPool::get_index(uint32_t size)
{
	int x = 0;
	int y = 1;
	int z = 0;
	if (size <= 128) {
		x = size - 1;
		y = 8;
		z = 0;
	} else if (size <= 256) {
		x = 16;
		y = z = 0;
	} else if (size <= 512) {
		x = 17;
		y = z = 0;
	} else if (size <= 1500) {
		x = 18;
		y = z = 0;
	} else if (size <= 64 * 1024) {
		x = size - 1;
		y = 4 * 1024;
		z = 19;
	} else {
		x = size - 1;
		y = 16 * 1024;
		y = 31;
	}
	return x/y + z;
}
}//namespace BlueSky


(完)

你可能感兴趣的:(C++,Linux)