add object memory pool

pull/1/head
yuqing 2014-06-05 14:11:53 +08:00
parent df3e985540
commit 80fba80f41
4 changed files with 325 additions and 3 deletions

View File

@ -1,7 +1,8 @@
Version 1.06 2014-05-30
Version 1.06 2014-06-05
* update source code from FastDFS V5.02
* add function short2buff and buff2short
* add object memory pool (fast_mblock.h and fast_mblock.c)
Version 1.05 2012-07-08
* update source code from FastDFS V3.09

View File

@ -8,13 +8,13 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \
logger.lo sockopt.lo base64.lo sched_thread.lo \
http_func.lo md5.lo pthread_func.lo local_ip_func.lo \
avl_tree.lo ioevent.lo ioevent_loop.lo fast_task_queue.lo \
fast_timer.lo process_ctrl.lo
fast_timer.lo process_ctrl.lo fast_mblock.lo
HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
shared_func.h pthread_func.h ini_file_reader.h _os_bits.h \
sockopt.h sched_thread.h http_func.h md5.h local_ip_func.h \
avl_tree.h ioevent.h ioevent_loop.h fast_task_queue.h \
fast_timer.h process_ctrl.h
fast_timer.h process_ctrl.h fast_mblock.h
ALL_OBJS = $(STATIC_OBJS) $(FAST_SHARED_OBJS)

225
src/fast_mblock.c Normal file
View File

@ -0,0 +1,225 @@
//fast_mblock.c
#include <errno.h>
#include <sys/resource.h>
#include <pthread.h>
#include "fast_mblock.h"
#include "logger.h"
#include "shared_func.h"
#include "pthread_func.h"
int fast_mblock_init(struct fast_mblock_man *mblock, const int element_size, \
const int alloc_elements_once)
{
int result;
if (element_size <= 0)
{
logError("file: "__FILE__", line: %d, " \
"invalid block size: %d", \
__LINE__, element_size);
return EINVAL;
}
mblock->element_size = element_size;
if (alloc_elements_once > 0)
{
mblock->alloc_elements_once = alloc_elements_once;
}
else
{
int block_size;
block_size = MEM_ALIGN(sizeof(struct fast_mblock_node) \
+ element_size);
mblock->alloc_elements_once = (1024 * 1024) / block_size;
}
if ((result=init_pthread_lock(&(mblock->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"init_pthread_lock fail, errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
mblock->malloc_chain_head = NULL;
mblock->free_chain_head = NULL;
return 0;
}
static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
{
struct fast_mblock_node *pNode;
struct fast_mblock_malloc *pMallocNode;
char *pNew;
char *pTrunkStart;
char *p;
char *pLast;
int block_size;
int alloc_size;
block_size = MEM_ALIGN(sizeof(struct fast_mblock_node) + \
mblock->element_size);
alloc_size = sizeof(struct fast_mblock_malloc) + block_size * \
mblock->alloc_elements_once;
pNew = (char *)malloc(alloc_size);
if (pNew == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, " \
"errno: %d, error info: %s", \
__LINE__, alloc_size, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
memset(pNew, 0, alloc_size);
pMallocNode = (struct fast_mblock_malloc *)pNew;
pTrunkStart = pNew + sizeof(struct fast_mblock_malloc);
pLast = pNew + (alloc_size - block_size);
for (p=pTrunkStart; p<pLast; p += block_size)
{
pNode = (struct fast_mblock_node *)p;
pNode->next = (struct fast_mblock_node *)(p + block_size);
}
((struct fast_mblock_node *)pLast)->next = NULL;
mblock->free_chain_head = (struct fast_mblock_node *)pTrunkStart;
pMallocNode->next = mblock->malloc_chain_head;
mblock->malloc_chain_head = pMallocNode;
return 0;
}
void fast_mblock_destroy(struct fast_mblock_man *mblock)
{
struct fast_mblock_malloc *pMallocNode;
struct fast_mblock_malloc *pMallocTmp;
if (mblock->malloc_chain_head == NULL)
{
return;
}
pMallocNode = mblock->malloc_chain_head;
while (pMallocNode != NULL)
{
pMallocTmp = pMallocNode;
pMallocNode = pMallocNode->next;
free(pMallocTmp);
}
mblock->malloc_chain_head = NULL;
mblock->free_chain_head = NULL;
pthread_mutex_destroy(&(mblock->lock));
}
struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock)
{
struct fast_mblock_node *pNode;
int result;
if ((result=pthread_mutex_lock(&(mblock->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return NULL;
}
if (mblock->free_chain_head != NULL)
{
pNode = mblock->free_chain_head;
mblock->free_chain_head = pNode->next;
}
else
{
if ((result=fast_mblock_prealloc(mblock)) == 0)
{
pNode = mblock->free_chain_head;
mblock->free_chain_head = pNode->next;
}
else
{
pNode = NULL;
}
}
if ((result=pthread_mutex_unlock(&(mblock->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return pNode;
}
int fast_mblock_free(struct fast_mblock_man *mblock, \
struct fast_mblock_node *pNode)
{
int result;
if ((result=pthread_mutex_lock(&(mblock->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
pNode->next = mblock->free_chain_head;
mblock->free_chain_head = pNode;
if ((result=pthread_mutex_unlock(&(mblock->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return 0;
}
int fast_mblock_count(struct fast_mblock_man *mblock)
{
struct fast_mblock_node *pNode;
int count;
int result;
if ((result=pthread_mutex_lock(&(mblock->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return -1;
}
count = 0;
pNode = mblock->free_chain_head;
while (pNode != NULL)
{
pNode = pNode->next;
count++;
}
if ((result=pthread_mutex_unlock(&(mblock->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return count;
}

96
src/fast_mblock.h Normal file
View File

@ -0,0 +1,96 @@
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS may be copied only under the terms of the GNU General
* Public License V3, which may be found in the FastDFS source kit.
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
//fast_mblock.h
#ifndef _FAST_MBLOCK_H
#define _FAST_MBLOCK_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "common_define.h"
#include "chain.h"
/* free node chain */
struct fast_mblock_node
{
struct fast_mblock_node *next;
char data[0]; //the data buffer
};
/* malloc chain */
struct fast_mblock_malloc
{
struct fast_mblock_malloc *next;
};
struct fast_mblock_man
{
struct fast_mblock_node *free_chain_head; //free node chain
struct fast_mblock_malloc *malloc_chain_head; //malloc chain to be freed
int element_size; //element size
int alloc_elements_once; //alloc elements once
pthread_mutex_t lock; //the lock for read / write free node chain
};
#ifdef __cplusplus
extern "C" {
#endif
/**
mblock init
parameters:
mblock: the mblock pointer
element_size: element size, such as sizeof(struct xxx)
alloc_elements_once: malloc elements once, 0 for malloc 1MB once
return error no, 0 for success, != 0 fail
*/
int fast_mblock_init(struct fast_mblock_man *mblock, const int element_size, \
const int alloc_elements_once);
/**
mblock destroy
parameters:
mblock: the mblock pointer
*/
void fast_mblock_destroy(struct fast_mblock_man *mblock);
/**
alloc a node from the mblock
parameters:
mblock: the mblock pointer
return the alloced node, return NULL if fail
*/
struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock);
/**
free a node (put a node to the mblock)
parameters:
mblock: the mblock pointer
pNode: the node to free
return the alloced node, return NULL if fail
*/
int fast_mblock_free(struct fast_mblock_man *mblock, \
struct fast_mblock_node *pNode);
/**
get node count of the mblock
parameters:
mblock: the mblock pointer
return the free node count of the mblock, return -1 if fail
*/
int fast_mblock_count(struct fast_mblock_man *mblock);
#ifdef __cplusplus
}
#endif
#endif