diff --git a/HISTORY b/HISTORY index b1b21ec..334df13 100644 --- a/HISTORY +++ b/HISTORY @@ -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 diff --git a/src/Makefile.in b/src/Makefile.in index ef7ecce..6e021b7 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -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) diff --git a/src/fast_mblock.c b/src/fast_mblock.c new file mode 100644 index 0000000..488a084 --- /dev/null +++ b/src/fast_mblock.c @@ -0,0 +1,225 @@ +//fast_mblock.c + +#include +#include +#include +#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; pnext = (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; +} + diff --git a/src/fast_mblock.h b/src/fast_mblock.h new file mode 100644 index 0000000..afc786f --- /dev/null +++ b/src/fast_mblock.h @@ -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 +#include +#include +#include +#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 +