您的位置:首页 > 其它

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

2016-07-01 23:52 573 查看
本文只给出功能代码,后续文章进行内存池相关知识的简介。

请思考几个问题:

0)为什么已经有了glibc的malloc/free,为什么还实现自己的线程池?,答:后续文章简介给出。

1)线程池的优缺点是什么?,答:后续文章简介给出。

2)本文的线程池是如何使用TSD来实现线程安全的?,答:使用了TSD的主要属性:每个线程的data都有自己的内存空间,相互之间互不影响。

3)本文实现的线程安全的线程池能否做到每个线程使用线程池申请内存时无竞争和不互相影响的效果?答:能,因为TSD就是做到了每个线程之间的data无影响。

4)本文为什么没有使用mutex互斥量来实现线程池?答:为了实现线程安全。

5)能否通过使用mutex互斥量实现一个线程池?答案是:能。

6)使用mutex互斥量实现的线程池,每个线程之间申请内存时可能会出现竞争现象!

7)请使用mutex互斥量实现一个线程池?答:后续给出功能代码。

#ifndef __BLUESKY_THREADSAFEMEMORY_H__
#define __BLUESKY_THREADSAFEMEMORY_H__

///编译时请执行 $g++ -c ./ThreadSafeMemory -o tsm.o -lpthread
///使用pthread_once系列函数时,编译时要添加-lpthread选项!
#include <stdio.h>	//for pthread_once系列函数
#include <pthread.h>//for pthread_once系列函数
#include <stdlib.h>	//for glibc malloc/free
#include <stddef.h> //for offsetof()
#include <stdint.h>	//for uint32_t and so on.
#include <string.h> //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 CThreadSafeMemory
{
private:
CThreadSafeMemory(){};
~CThreadSafeMemory(){};
public:
static void CreateMemoryPool();
static void DestroyMemoryPool();
static void* Malloc(uint32_t);
static void Free(void* ptr);
private:
static void *proc_malloc(struct head* memory_pool, uint32_t size);
static void proc_free(struct head* memory_pool, void* ptr);
//< 为当前线程创建其私有数据的key
static void create_memory_key();
static void free_memory_key(void* threadData);
//< 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 pthread_key_t memory_pool_key;
};//CThreadSafeMemory

}//namespace BlueSky

#endif


#include "ThreadSafeMemory.h"
namespace BlueSky{

struct head 	CThreadSafeMemory::m_memory_template[SIZE_TYPE_NUM];
pthread_key_t 	CThreadSafeMemory::memory_pool_key;

void CThreadSafeMemory::CreateMemoryPool()
{
//< create key(memory_pool_key) for TSD
pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once( &once, create_memory_key );

//< create TSD(memory_pool) for current thread
struct head* memory_pool = new struct head[SIZE_TYPE_NUM];
memcpy ( memory_pool, m_memory_template, sizeof(struct head) * SIZE_TYPE_NUM );

//< bind TSD and key(memory_pool + memory_pool_key)
pthread_setspecific( memory_pool_key, memory_pool );
}
void CThreadSafeMemory::DestroyMemoryPool()
{
//< unbind TSD and key(memory_pool - memory_pool_key)
pthread_key_delete ( memory_pool_key );
}
void* CThreadSafeMemory::Malloc(uint32_t siz)
{
struct head* pool = (head*)pthread_getspecific ( memory_pool_key );
return proc_malloc(pool, siz);
}
void CThreadSafeMemory::Free(void* ptr)
{
struct head* pool = (head*)pthread_getspecific( memory_pool_key);
proc_free(pool, ptr);
}
void* CThreadSafeMemory::proc_malloc(struct head* pool, uint32_t size)
{
struct node* ret  = NULL;
/// 情况1:申请超过256K的buf时,直接使用glibc的malloc来申请
if (size > 256 * 1024 || NULL == 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 );
ret = pool[index].head;
/// 情况2:从pool中取buf,有空闲buf的node,取出此node并将其buf返回给用户
if (ret)
{
pool[index].head = ret->next;
ret->next = NULL;
pool[index].nodes_size -= 1;
return ret->buf;
}
/// 情况3:从pool中取buf,无空闲buf的ndoe, malloc一个node给用户
/// 用户free此buf时再将其放入到pool中
uint32_t len = sizeof(struct node) + pool[index].mem_size;
ret = (struct node*)malloc( len );
ret->index = index;
ret->mem_size = pool[index].mem_size;
ret->next = NULL;
return ret->buf;
}
void CThreadSafeMemory::proc_free(struct head* pool, void* ptr)
{
//获取得到buf所在struct node的起始指针(即属主node的对象指针pnode)
struct node* pnode = (struct node*)((char*)ptr - offsetof(struct node, buf));
int index = pnode->index;
if (index == -1) {
free(pnode);
return ;
}
bool full = pool[index].nodes_size == pool[index].nodes_cap;
if (full) {
free(pnode);
return ;
}
struct head list = pool[index];
if (list.head == NULL) {
list.head = pnode;
list.tail = pnode;
}
else {
list.tail->next = pnode;
list.tail = pnode;
}
list.nodes_size += 1;
return;
}
//< 为当前线程创建其私有数据的key
void CThreadSafeMemory::create_memory_key()
{
//创建TSD的key时,也注册释放key的函数
pthread_key_create ( &memory_pool_key, free_memory_key );
}
void CThreadSafeMemory::free_memory_key(void* pool)
{
struct head* mem_pool = (struct head*)pool;
struct node* pnode = NULL;
for (int i = 0; i < SIZE_TYPE_NUM; ++i)
{
struct head list = mem_pool[i];
while (list.nodes_size > 0)
{
pnode = list.head;
list.head = pnode->next;
free(pnode);
pnode = NULL;
list.nodes_size -= 1;
}
}
}
//< get size's hash value as memory-list-array's index
inline int CThreadSafeMemory::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


进行编译,编译成功,如下图所示:



<完>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: