From fb5abf592745da18beaca9b2b22c9d92afd5159a Mon Sep 17 00:00:00 2001 From: Yu Qing Date: Wed, 4 Nov 2015 17:19:36 +0800 Subject: [PATCH] add fast_allocator --- HISTORY | 1 + src/Makefile.in | 6 +- src/fast_allocator.c | 200 +++++++++++++++++++++++++++++++++++++++++++ src/fast_allocator.h | 97 +++++++++++++++++++++ 4 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 src/fast_allocator.c create mode 100644 src/fast_allocator.h diff --git a/HISTORY b/HISTORY index 0527e9a..43f26dc 100644 --- a/HISTORY +++ b/HISTORY @@ -8,6 +8,7 @@ Version 1.23 2015-11-04 ONLY support Linux and FreeBSD * delay task can execute in a new thread * fast_mblock reclaimed object pool + * add fast_allocator Version 1.22 2015-10-10 * export php function: fastcommon_get_first_local_ip diff --git a/src/Makefile.in b/src/Makefile.in index a071817..d724fab 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -10,21 +10,21 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.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_mblock.lo \ - connection_pool.lo fast_mpool.lo + connection_pool.lo fast_mpool.lo fast_allocator.lo FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ logger.o sockopt.o base64.o sched_thread.o \ http_func.o md5.o pthread_func.o local_ip_func.o \ avl_tree.o ioevent.o ioevent_loop.o fast_task_queue.o \ fast_timer.o process_ctrl.o fast_mblock.o \ - connection_pool.o fast_mpool.o + connection_pool.o fast_mpool.o fast_allocator.o HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \ shared_func.h pthread_func.h ini_file_reader.h _os_define.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_mblock.h \ - connection_pool.h fast_mpool.h + connection_pool.h fast_mpool.h fast_allocator.h ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS) diff --git a/src/fast_allocator.c b/src/fast_allocator.c new file mode 100644 index 0000000..5dd0b82 --- /dev/null +++ b/src/fast_allocator.c @@ -0,0 +1,200 @@ +//fast_allocator.c + +#include +#include +#include "logger.h" +#include "shared_func.h" +#include "fast_allocator.h" + +static int region_init(struct fast_allocator_context *acontext, + struct fast_region_info *region) +{ + int result; + int bytes; + int element_size; + int allocator_count; + struct fast_mblock_man *mblock; + + allocator_count = (region->end - region->start) / region->step; + bytes = sizeof(struct fast_mblock_man) * allocator_count; + region->allocators = (struct fast_mblock_man *)malloc(bytes); + if (region->allocators == NULL) + { + result = errno != 0 ? errno : ENOMEM; + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, errno: %d, error info: %s", + __LINE__, bytes, result, STRERROR(result)); + return result; + } + memset(region->allocators, 0, bytes); + + result = 0; + mblock = region->allocators; + for (element_size=region->start+region->step; element_size<=region->end; + element_size+=region->step,mblock++) + { + result = fast_mblock_init_ex(mblock, element_size, + region->alloc_elements_once, NULL, acontext->need_lock); + if (result != 0) + { + break; + } + } + + return result; +} + +static void region_destroy(struct fast_allocator_context *acontext, + struct fast_region_info *region) +{ + int element_size; + int allocator_count; + struct fast_mblock_man *mblock; + + allocator_count = (region->end - region->start) / region->step; + mblock = region->allocators; + for (element_size=region->start+region->step; element_size<=region->end; + element_size+=region->step,mblock++) + { + fast_mblock_destroy(mblock); + } + + free(region->allocators); + region->allocators = NULL; +} + +int fast_allocator_init_ex(struct fast_allocator_context *acontext, + struct fast_region_info *regions, const int region_count, + const bool need_lock) +{ + int result; + int bytes; + int previous_end; + struct fast_region_info *pRegion; + struct fast_region_info *region_end; + + memset(acontext, 0, sizeof(*acontext)); + if (region_count <= 0) + { + return EINVAL; + } + + bytes = sizeof(struct fast_region_info) * region_count; + acontext->regions = (struct fast_region_info *)malloc(bytes); + if (acontext->regions == NULL) + { + result = errno != 0 ? errno : ENOMEM; + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, errno: %d, error info: %s", + __LINE__, bytes, result, STRERROR(result)); + return result; + } + memcpy(acontext->regions, regions, bytes); + acontext->region_count = region_count; + acontext->need_lock = need_lock; + result = 0; + previous_end = 0; + region_end = acontext->regions + acontext->region_count; + for (pRegion=acontext->regions; pRegionstart != previous_end) + { + logError("file: "__FILE__", line: %d, " + "invalid start: %d != last end: %d", + __LINE__, pRegion->start, previous_end); + result = EINVAL; + break; + } + if (pRegion->start >= pRegion->end) + { + logError("file: "__FILE__", line: %d, " + "invalid start: %d >= end: %d", + __LINE__, pRegion->start, pRegion->end); + result = EINVAL; + break; + } + if (pRegion->step <= 0) + { + logError("file: "__FILE__", line: %d, " + "invalid step: %d", + __LINE__, pRegion->step); + result = EINVAL; + break; + } + if (pRegion->start % pRegion->step != 0) + { + logError("file: "__FILE__", line: %d, " + "invalid start: %d, must multiple of step: %d", + __LINE__, pRegion->start, pRegion->step); + result = EINVAL; + break; + } + if (pRegion->end % pRegion->step != 0) + { + logError("file: "__FILE__", line: %d, " + "invalid end: %d, must multiple of step: %d", + __LINE__, pRegion->end, pRegion->step); + result = EINVAL; + break; + } + previous_end = pRegion->end; + + if ((result=region_init(acontext, pRegion)) != 0) + { + break; + } + } + + return result; +} + +#define INIT_REGION(region, _start, _end, _step, _alloc_once) \ + do { \ + region.start = _start; \ + region.end = _end; \ + region.step = _step; \ + region.alloc_elements_once = _alloc_once; \ + } while(0) + +int fast_allocator_init(struct fast_allocator_context *acontext, + const bool need_lock) +{ +#define DEFAULT_REGION_COUNT 6 + + struct fast_region_info regions[DEFAULT_REGION_COUNT]; + + INIT_REGION(regions[0], 0, 256, 8, 4096); + INIT_REGION(regions[1], 256, 1024, 16, 1024); + INIT_REGION(regions[2], 1024, 4096, 64, 256); + INIT_REGION(regions[3], 4096, 16384, 256, 64); + INIT_REGION(regions[4], 16384, 65536, 1024, 16); + + return fast_allocator_init_ex(acontext, regions, + DEFAULT_REGION_COUNT, need_lock); +} + +void fast_allocator_destroy(struct fast_allocator_context *acontext) +{ + struct fast_region_info *pRegion; + struct fast_region_info *region_end; + + region_end = acontext->regions + acontext->region_count; + for (pRegion=acontext->regions; pRegionregions); + acontext->regions = NULL; +} + +void* fast_allocator_alloc(struct fast_allocator_context *acontext, + const int bytes) +{ + return NULL; +} + +void fast_allocator_free(struct fast_allocator_context *acontext, void *ptr) +{ +} + diff --git a/src/fast_allocator.h b/src/fast_allocator.h new file mode 100644 index 0000000..6268fee --- /dev/null +++ b/src/fast_allocator.h @@ -0,0 +1,97 @@ +/** +* 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_allocator.h + +#ifndef _FAST_ALLOCATOR_H +#define _FAST_ALLOCATOR_H + +#include +#include +#include +#include +#include "common_define.h" +#include "fast_mblock.h" + +struct fast_region_info +{ + int start; + int end; + int step; + int alloc_elements_once; + struct fast_mblock_man *allocators; +}; + +struct fast_allocator_context +{ + struct fast_region_info *regions; + int region_count; + + int64_t alloc_bytes; + bool need_lock; //if need mutex lock for acontext +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** +allocator init by default region allocators +parameters: + acontext: the context pointer + need_lock: if need lock +return error no, 0 for success, != 0 fail +*/ +int fast_allocator_init(struct fast_allocator_context *acontext, + const bool need_lock); + +/** +allocator init +parameters: + acontext: the context pointer + regions: the region array + region_count: the region count + need_lock: if need lock +return error no, 0 for success, != 0 fail +*/ +int fast_allocator_init_ex(struct fast_allocator_context *acontext, + struct fast_region_info *regions, const int region_count, + const bool need_lock); + +/** +allocator destroy +parameters: + acontext: the context pointer +*/ +void fast_allocator_destroy(struct fast_allocator_context *acontext); + +/** +alloc memory from the context +parameters: + acontext: the context pointer + bytes: alloc bytes +return the alloced pointer, return NULL if fail +*/ +void* fast_allocator_alloc(struct fast_allocator_context *acontext, + const int bytes); + +/** +free a node (put a node to the context) +parameters: + acontext: the context pointer + ptr: the pointer to free +return none +*/ +void fast_allocator_free(struct fast_allocator_context *acontext, void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif +