add fast_allocator
parent
0fe90e35da
commit
fb5abf5927
1
HISTORY
1
HISTORY
|
|
@ -8,6 +8,7 @@ Version 1.23 2015-11-04
|
||||||
ONLY support Linux and FreeBSD
|
ONLY support Linux and FreeBSD
|
||||||
* delay task can execute in a new thread
|
* delay task can execute in a new thread
|
||||||
* fast_mblock reclaimed object pool
|
* fast_mblock reclaimed object pool
|
||||||
|
* add fast_allocator
|
||||||
|
|
||||||
Version 1.22 2015-10-10
|
Version 1.22 2015-10-10
|
||||||
* export php function: fastcommon_get_first_local_ip
|
* export php function: fastcommon_get_first_local_ip
|
||||||
|
|
|
||||||
|
|
@ -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 \
|
http_func.lo md5.lo pthread_func.lo local_ip_func.lo \
|
||||||
avl_tree.lo ioevent.lo ioevent_loop.lo fast_task_queue.lo \
|
avl_tree.lo ioevent.lo ioevent_loop.lo fast_task_queue.lo \
|
||||||
fast_timer.lo process_ctrl.lo fast_mblock.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 \
|
FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
|
||||||
logger.o sockopt.o base64.o sched_thread.o \
|
logger.o sockopt.o base64.o sched_thread.o \
|
||||||
http_func.o md5.o pthread_func.o local_ip_func.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 \
|
avl_tree.o ioevent.o ioevent_loop.o fast_task_queue.o \
|
||||||
fast_timer.o process_ctrl.o fast_mblock.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 \
|
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 \
|
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 \
|
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 \
|
avl_tree.h ioevent.h ioevent_loop.h fast_task_queue.h \
|
||||||
fast_timer.h process_ctrl.h fast_mblock.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)
|
ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
//fast_allocator.c
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#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; pRegion<region_end; pRegion++)
|
||||||
|
{
|
||||||
|
if (pRegion->start != 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; pRegion<region_end; pRegion++)
|
||||||
|
{
|
||||||
|
region_destroy(acontext, pRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(acontext->regions);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#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
|
||||||
|
|
||||||
Loading…
Reference in New Issue