You've already forked qlg.tsgz.moe
Init Repo
This commit is contained in:
174
vendor/swoole/src/memory/Buffer.c
vendored
Executable file
174
vendor/swoole/src/memory/Buffer.c
vendored
Executable file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/**
|
||||
* create new buffer
|
||||
*/
|
||||
swBuffer* swBuffer_new(int trunk_size)
|
||||
{
|
||||
swBuffer *buffer = sw_malloc(sizeof(swBuffer));
|
||||
if (buffer == NULL)
|
||||
{
|
||||
swWarn("malloc for buffer failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bzero(buffer, sizeof(swBuffer));
|
||||
buffer->trunk_size = trunk_size;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* create new trunk
|
||||
*/
|
||||
swBuffer_trunk *swBuffer_new_trunk(swBuffer *buffer, uint32_t type, uint32_t size)
|
||||
{
|
||||
swBuffer_trunk *chunk = sw_malloc(sizeof(swBuffer_trunk));
|
||||
if (chunk == NULL)
|
||||
{
|
||||
swWarn("malloc for trunk failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bzero(chunk, sizeof(swBuffer_trunk));
|
||||
|
||||
//require alloc memory
|
||||
if (type == SW_CHUNK_DATA && size > 0)
|
||||
{
|
||||
void *buf = sw_malloc(size);
|
||||
if (buf == NULL)
|
||||
{
|
||||
swWarn("malloc(%d) for data failed. Error: %s[%d]", size, strerror(errno), errno);
|
||||
sw_free(chunk);
|
||||
return NULL;
|
||||
}
|
||||
chunk->size = size;
|
||||
chunk->store.ptr = buf;
|
||||
}
|
||||
|
||||
chunk->type = type;
|
||||
buffer->trunk_num ++;
|
||||
|
||||
if (buffer->head == NULL)
|
||||
{
|
||||
buffer->tail = buffer->head = chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->tail->next = chunk;
|
||||
buffer->tail = chunk;
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* pop the head chunk
|
||||
*/
|
||||
void swBuffer_pop_trunk(swBuffer *buffer, swBuffer_trunk *chunk)
|
||||
{
|
||||
if (chunk->next == NULL)
|
||||
{
|
||||
buffer->head = NULL;
|
||||
buffer->tail = NULL;
|
||||
buffer->length = 0;
|
||||
buffer->trunk_num = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->head = chunk->next;
|
||||
buffer->length -= chunk->length;
|
||||
buffer->trunk_num--;
|
||||
}
|
||||
if (chunk->type == SW_CHUNK_DATA)
|
||||
{
|
||||
sw_free(chunk->store.ptr);
|
||||
}
|
||||
if (chunk->destroy)
|
||||
{
|
||||
chunk->destroy(chunk);
|
||||
}
|
||||
sw_free(chunk);
|
||||
}
|
||||
|
||||
/**
|
||||
* free buffer
|
||||
*/
|
||||
int swBuffer_free(swBuffer *buffer)
|
||||
{
|
||||
volatile swBuffer_trunk *chunk = buffer->head;
|
||||
void * *will_free_trunk; //free the point
|
||||
while (chunk != NULL)
|
||||
{
|
||||
if (chunk->type == SW_CHUNK_DATA)
|
||||
{
|
||||
sw_free(chunk->store.ptr);
|
||||
}
|
||||
will_free_trunk = (void *) chunk;
|
||||
chunk = chunk->next;
|
||||
sw_free(will_free_trunk);
|
||||
}
|
||||
sw_free(buffer);
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* append to buffer queue
|
||||
*/
|
||||
int swBuffer_append(swBuffer *buffer, void *data, uint32_t size)
|
||||
{
|
||||
swBuffer_trunk *chunk = swBuffer_new_trunk(buffer, SW_CHUNK_DATA, size);
|
||||
if (chunk == NULL)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
buffer->length += size;
|
||||
chunk->length = size;
|
||||
|
||||
memcpy(chunk->store.ptr, data, size);
|
||||
|
||||
swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|size=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, size,
|
||||
chunk->length, chunk);
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* print buffer
|
||||
*/
|
||||
void swBuffer_debug(swBuffer *buffer, int print_data)
|
||||
{
|
||||
int i = 0;
|
||||
volatile swBuffer_trunk *trunk = buffer->head;
|
||||
printf("%s\n%s\n", SW_START_LINE, __func__);
|
||||
while (trunk != NULL)
|
||||
{
|
||||
i++;
|
||||
printf("%d.\tlen=%d", i, trunk->length);
|
||||
if (print_data)
|
||||
{
|
||||
printf("\tdata=%s", (char *) trunk->store.ptr);
|
||||
}
|
||||
printf("\n");
|
||||
trunk = trunk->next;
|
||||
}
|
||||
printf("%s\n%s\n", SW_END_LINE, __func__);
|
||||
}
|
249
vendor/swoole/src/memory/FixedPool.c
vendored
Executable file
249
vendor/swoole/src/memory/FixedPool.c
vendored
Executable file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
|
||||
static void swFixedPool_init(swFixedPool *object);
|
||||
static void* swFixedPool_alloc(swMemoryPool *pool, uint32_t size);
|
||||
static void swFixedPool_free(swMemoryPool *pool, void *ptr);
|
||||
static void swFixedPool_destroy(swMemoryPool *pool);
|
||||
|
||||
void swFixedPool_debug_slice(swFixedPool_slice *slice);
|
||||
|
||||
/**
|
||||
* create new FixedPool, random alloc/free fixed size memory
|
||||
*/
|
||||
swMemoryPool* swFixedPool_new(uint32_t slice_num, uint32_t slice_size, uint8_t shared)
|
||||
{
|
||||
size_t size = slice_size * slice_num + slice_num * sizeof(swFixedPool_slice);
|
||||
size_t alloc_size = size + sizeof(swFixedPool) + sizeof(swMemoryPool);
|
||||
void *memory = (shared == 1) ? sw_shm_malloc(alloc_size) : sw_malloc(alloc_size);
|
||||
|
||||
swFixedPool *object = memory;
|
||||
memory += sizeof(swFixedPool);
|
||||
bzero(object, sizeof(swFixedPool));
|
||||
|
||||
object->shared = shared;
|
||||
object->slice_num = slice_num;
|
||||
object->slice_size = slice_size;
|
||||
object->size = size;
|
||||
|
||||
swMemoryPool *pool = memory;
|
||||
memory += sizeof(swMemoryPool);
|
||||
pool->object = object;
|
||||
pool->alloc = swFixedPool_alloc;
|
||||
pool->free = swFixedPool_free;
|
||||
pool->destroy = swFixedPool_destroy;
|
||||
|
||||
object->memory = memory;
|
||||
|
||||
/**
|
||||
* init linked list
|
||||
*/
|
||||
swFixedPool_init(object);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* create new FixedPool, Using the given memory
|
||||
*/
|
||||
swMemoryPool* swFixedPool_new2(uint32_t slice_size, void *memory, size_t size)
|
||||
{
|
||||
swFixedPool *object = memory;
|
||||
memory += sizeof(swFixedPool);
|
||||
bzero(object, sizeof(swFixedPool));
|
||||
|
||||
object->slice_size = slice_size;
|
||||
object->size = size - sizeof(swMemoryPool) - sizeof(swFixedPool);
|
||||
object->slice_num = object->size / (slice_size + sizeof(swFixedPool_slice));
|
||||
|
||||
swMemoryPool *pool = memory;
|
||||
memory += sizeof(swMemoryPool);
|
||||
bzero(pool, sizeof(swMemoryPool));
|
||||
|
||||
pool->object = object;
|
||||
pool->alloc = swFixedPool_alloc;
|
||||
pool->free = swFixedPool_free;
|
||||
pool->destroy = swFixedPool_destroy;
|
||||
|
||||
object->memory = memory;
|
||||
|
||||
/**
|
||||
* init linked list
|
||||
*/
|
||||
swFixedPool_init(object);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* linked list
|
||||
*/
|
||||
static void swFixedPool_init(swFixedPool *object)
|
||||
{
|
||||
swFixedPool_slice *slice;
|
||||
void *cur = object->memory;
|
||||
void *max = object->memory + object->size;
|
||||
do
|
||||
{
|
||||
slice = (swFixedPool_slice *) cur;
|
||||
bzero(slice, sizeof(swFixedPool_slice));
|
||||
|
||||
if (object->head != NULL)
|
||||
{
|
||||
object->head->pre = slice;
|
||||
slice->next = object->head;
|
||||
}
|
||||
else
|
||||
{
|
||||
object->tail = slice;
|
||||
}
|
||||
|
||||
object->head = slice;
|
||||
cur += (sizeof(swFixedPool_slice) + object->slice_size);
|
||||
|
||||
if (cur < max)
|
||||
{
|
||||
slice->pre = (swFixedPool_slice *) cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice->pre = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static void* swFixedPool_alloc(swMemoryPool *pool, uint32_t size)
|
||||
{
|
||||
swFixedPool *object = pool->object;
|
||||
swFixedPool_slice *slice;
|
||||
|
||||
slice = object->head;
|
||||
|
||||
if (slice->lock == 0)
|
||||
{
|
||||
slice->lock = 1;
|
||||
object->slice_use ++;
|
||||
/**
|
||||
* move next slice to head (idle list)
|
||||
*/
|
||||
object->head = slice->next;
|
||||
slice->next->pre = NULL;
|
||||
|
||||
/*
|
||||
* move this slice to tail (busy list)
|
||||
*/
|
||||
object->tail->next = slice;
|
||||
slice->next = NULL;
|
||||
slice->pre = object->tail;
|
||||
object->tail = slice;
|
||||
|
||||
return slice->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void swFixedPool_free(swMemoryPool *pool, void *ptr)
|
||||
{
|
||||
swFixedPool *object = pool->object;
|
||||
swFixedPool_slice *slice;
|
||||
|
||||
assert(ptr > object->memory && ptr < object->memory + object->size);
|
||||
|
||||
slice = ptr - sizeof(swFixedPool_slice);
|
||||
|
||||
if (slice->lock)
|
||||
{
|
||||
object->slice_use--;
|
||||
}
|
||||
|
||||
slice->lock = 0;
|
||||
|
||||
//list head, AB
|
||||
if (slice->pre == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//list tail, DE
|
||||
if (slice->next == NULL)
|
||||
{
|
||||
slice->pre->next = NULL;
|
||||
object->tail = slice->pre;
|
||||
}
|
||||
//middle BCD
|
||||
else
|
||||
{
|
||||
slice->pre->next = slice->next;
|
||||
slice->next->pre = slice->pre;
|
||||
}
|
||||
|
||||
slice->pre = NULL;
|
||||
slice->next = object->head;
|
||||
object->head->pre = slice;
|
||||
object->head = slice;
|
||||
}
|
||||
|
||||
static void swFixedPool_destroy(swMemoryPool *pool)
|
||||
{
|
||||
swFixedPool *object = pool->object;
|
||||
if (object->shared)
|
||||
{
|
||||
sw_shm_free(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
sw_free(object);
|
||||
}
|
||||
}
|
||||
|
||||
void swFixedPool_debug(swMemoryPool *pool)
|
||||
{
|
||||
int line = 0;
|
||||
swFixedPool *object = pool->object;
|
||||
swFixedPool_slice *slice = object->head;
|
||||
|
||||
printf("===============================%s=================================\n", __FUNCTION__);
|
||||
while (slice != NULL)
|
||||
{
|
||||
if (slice->next == slice)
|
||||
{
|
||||
printf("-------------------@@@@@@@@@@@@@@@@@@@@@@----------------\n");
|
||||
|
||||
}
|
||||
printf("#%d\t", line);
|
||||
swFixedPool_debug_slice(slice);
|
||||
|
||||
slice = slice->next;
|
||||
line++;
|
||||
if (line > 100)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void swFixedPool_debug_slice(swFixedPool_slice *slice)
|
||||
{
|
||||
printf("Slab[%p]\t", slice);
|
||||
printf("pre=%p\t", slice->pre);
|
||||
printf("next=%p\t", slice->next);
|
||||
printf("tag=%d\t", slice->lock);
|
||||
printf("data=%p\n", slice->data);
|
||||
}
|
50
vendor/swoole/src/memory/Malloc.c
vendored
Executable file
50
vendor/swoole/src/memory/Malloc.c
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
|
||||
static void* swMalloc_alloc(swMemoryPool *pool, uint32_t size);
|
||||
static void swMalloc_free(swMemoryPool *pool, void *ptr);
|
||||
static void swMalloc_destroy(swMemoryPool *pool);
|
||||
|
||||
swMemoryPool* swMalloc_new()
|
||||
{
|
||||
swMemoryPool *pool = sw_malloc(sizeof(swMemoryPool));
|
||||
if (pool == NULL)
|
||||
{
|
||||
swSysError("mallc(%ld) failed.", sizeof(swMemoryPool));
|
||||
return NULL;
|
||||
}
|
||||
pool->alloc = swMalloc_alloc;
|
||||
pool->free = swMalloc_free;
|
||||
pool->destroy = swMalloc_destroy;
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void* swMalloc_alloc(swMemoryPool *pool, uint32_t size)
|
||||
{
|
||||
return sw_malloc(size);
|
||||
}
|
||||
|
||||
static void swMalloc_free(swMemoryPool *pool, void *ptr)
|
||||
{
|
||||
sw_free(ptr);
|
||||
}
|
||||
|
||||
static void swMalloc_destroy(swMemoryPool *pool)
|
||||
{
|
||||
sw_free(pool);
|
||||
}
|
143
vendor/swoole/src/memory/MemoryGlobal.c
vendored
Executable file
143
vendor/swoole/src/memory/MemoryGlobal.c
vendored
Executable file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
|
||||
#define SW_MIN_PAGE_SIZE 4096
|
||||
|
||||
typedef struct _swMemoryGlobal_page
|
||||
{
|
||||
struct _swMemoryGlobal_page *next;
|
||||
char memory[0];
|
||||
} swMemoryGlobal_page;
|
||||
|
||||
typedef struct _swMemoryGlobal
|
||||
{
|
||||
uint8_t shared;
|
||||
uint32_t pagesize;
|
||||
swLock lock;
|
||||
swMemoryGlobal_page *root_page;
|
||||
swMemoryGlobal_page *current_page;
|
||||
uint32_t current_offset;
|
||||
} swMemoryGlobal;
|
||||
|
||||
static void *swMemoryGlobal_alloc(swMemoryPool *pool, uint32_t size);
|
||||
static void swMemoryGlobal_free(swMemoryPool *pool, void *ptr);
|
||||
static void swMemoryGlobal_destroy(swMemoryPool *poll);
|
||||
static swMemoryGlobal_page* swMemoryGlobal_new_page(swMemoryGlobal *gm);
|
||||
|
||||
swMemoryPool* swMemoryGlobal_new(uint32_t pagesize, uint8_t shared)
|
||||
{
|
||||
swMemoryGlobal gm, *gm_ptr;
|
||||
assert(pagesize >= SW_MIN_PAGE_SIZE);
|
||||
bzero(&gm, sizeof(swMemoryGlobal));
|
||||
|
||||
gm.shared = shared;
|
||||
gm.pagesize = pagesize;
|
||||
|
||||
swMemoryGlobal_page *page = swMemoryGlobal_new_page(&gm);
|
||||
if (page == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (swMutex_create(&gm.lock, shared) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gm.root_page = page;
|
||||
|
||||
gm_ptr = (swMemoryGlobal *) page->memory;
|
||||
gm.current_offset += sizeof(swMemoryGlobal);
|
||||
|
||||
swMemoryPool *allocator = (swMemoryPool *) (page->memory + gm.current_offset);
|
||||
gm.current_offset += sizeof(swMemoryPool);
|
||||
|
||||
allocator->object = gm_ptr;
|
||||
allocator->alloc = swMemoryGlobal_alloc;
|
||||
allocator->destroy = swMemoryGlobal_destroy;
|
||||
allocator->free = swMemoryGlobal_free;
|
||||
|
||||
memcpy(gm_ptr, &gm, sizeof(gm));
|
||||
return allocator;
|
||||
}
|
||||
|
||||
static swMemoryGlobal_page* swMemoryGlobal_new_page(swMemoryGlobal *gm)
|
||||
{
|
||||
swMemoryGlobal_page *page = (gm->shared == 1) ? sw_shm_malloc(gm->pagesize) : sw_malloc(gm->pagesize);
|
||||
if (page == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
bzero(page, gm->pagesize);
|
||||
page->next = NULL;
|
||||
|
||||
if (gm->current_page != NULL)
|
||||
{
|
||||
gm->current_page->next = page;
|
||||
}
|
||||
|
||||
gm->current_page = page;
|
||||
gm->current_offset = 0;
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
static void *swMemoryGlobal_alloc(swMemoryPool *pool, uint32_t size)
|
||||
{
|
||||
swMemoryGlobal *gm = pool->object;
|
||||
gm->lock.lock(&gm->lock);
|
||||
if (size > gm->pagesize - sizeof(swMemoryGlobal_page))
|
||||
{
|
||||
swWarn("failed to alloc %d bytes, exceed the maximum size[%d].", size, gm->pagesize - (int) sizeof(swMemoryGlobal_page));
|
||||
gm->lock.unlock(&gm->lock);
|
||||
return NULL;
|
||||
}
|
||||
if (gm->current_offset + size > gm->pagesize - sizeof(swMemoryGlobal_page))
|
||||
{
|
||||
swMemoryGlobal_page *page = swMemoryGlobal_new_page(gm);
|
||||
if (page == NULL)
|
||||
{
|
||||
swWarn("swMemoryGlobal_alloc alloc memory error.");
|
||||
gm->lock.unlock(&gm->lock);
|
||||
return NULL;
|
||||
}
|
||||
gm->current_page = page;
|
||||
}
|
||||
void *mem = gm->current_page->memory + gm->current_offset;
|
||||
gm->current_offset += size;
|
||||
gm->lock.unlock(&gm->lock);
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void swMemoryGlobal_free(swMemoryPool *pool, void *ptr)
|
||||
{
|
||||
swWarn("swMemoryGlobal Allocator don't need to release.");
|
||||
}
|
||||
|
||||
static void swMemoryGlobal_destroy(swMemoryPool *poll)
|
||||
{
|
||||
swMemoryGlobal *gm = poll->object;
|
||||
swMemoryGlobal_page *page = gm->root_page;
|
||||
swMemoryGlobal_page *next;
|
||||
|
||||
do
|
||||
{
|
||||
next = page->next;
|
||||
sw_shm_free(page);
|
||||
page = next;
|
||||
} while (page);
|
||||
}
|
211
vendor/swoole/src/memory/RingBuffer.c
vendored
Executable file
211
vendor/swoole/src/memory/RingBuffer.c
vendored
Executable file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t shared;
|
||||
uint8_t status;
|
||||
uint32_t size;
|
||||
uint32_t alloc_offset;
|
||||
uint32_t collect_offset;
|
||||
uint32_t alloc_count;
|
||||
sw_atomic_t free_count;
|
||||
void *memory;
|
||||
} swRingBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t lock;
|
||||
uint16_t index;
|
||||
uint32_t length;
|
||||
char data[0];
|
||||
} swRingBuffer_item;
|
||||
|
||||
static void swRingBuffer_destory(swMemoryPool *pool);
|
||||
static void* swRingBuffer_alloc(swMemoryPool *pool, uint32_t size);
|
||||
static void swRingBuffer_free(swMemoryPool *pool, void *ptr);
|
||||
|
||||
#ifdef SW_RINGBUFFER_DEBUG
|
||||
static void swRingBuffer_print(swRingBuffer *object, char *prefix);
|
||||
|
||||
static void swRingBuffer_print(swRingBuffer *object, char *prefix)
|
||||
{
|
||||
printf("%s: size=%d, status=%d, alloc_count=%d, free_count=%d, offset=%d, next_offset=%d\n", prefix, object->size,
|
||||
object->status, object->alloc_count, object->free_count, object->alloc_offset, object->collect_offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
swMemoryPool *swRingBuffer_new(uint32_t size, uint8_t shared)
|
||||
{
|
||||
void *mem = (shared == 1) ? sw_shm_malloc(size) : sw_malloc(size);
|
||||
if (mem == NULL)
|
||||
{
|
||||
swWarn("malloc(%d) failed.", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
swRingBuffer *object = mem;
|
||||
mem += sizeof(swRingBuffer);
|
||||
bzero(object, sizeof(swRingBuffer));
|
||||
|
||||
object->size = (size - sizeof(swRingBuffer) - sizeof(swMemoryPool));
|
||||
object->shared = shared;
|
||||
|
||||
swMemoryPool *pool = mem;
|
||||
mem += sizeof(swMemoryPool);
|
||||
|
||||
pool->object = object;
|
||||
pool->destroy = swRingBuffer_destory;
|
||||
pool->free = swRingBuffer_free;
|
||||
pool->alloc = swRingBuffer_alloc;
|
||||
|
||||
object->memory = mem;
|
||||
|
||||
swDebug("memory: ptr=%p", mem);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void swRingBuffer_collect(swRingBuffer *object)
|
||||
{
|
||||
swRingBuffer_item *item;
|
||||
sw_atomic_t *free_count = &object->free_count;
|
||||
|
||||
int count = object->free_count;
|
||||
int i;
|
||||
uint32_t n_size;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
item = object->memory + object->collect_offset;
|
||||
if (item->lock == 0)
|
||||
{
|
||||
n_size = item->length + sizeof(swRingBuffer_item);
|
||||
|
||||
object->collect_offset += n_size;
|
||||
|
||||
if (object->collect_offset + sizeof(swRingBuffer_item) >object->size || object->collect_offset >= object->size)
|
||||
{
|
||||
object->collect_offset = 0;
|
||||
object->status = 0;
|
||||
}
|
||||
sw_atomic_fetch_sub(free_count, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void* swRingBuffer_alloc(swMemoryPool *pool, uint32_t size)
|
||||
{
|
||||
assert(size > 0);
|
||||
|
||||
swRingBuffer *object = pool->object;
|
||||
swRingBuffer_item *item;
|
||||
uint32_t capacity;
|
||||
|
||||
uint32_t alloc_size = size + sizeof(swRingBuffer_item);
|
||||
|
||||
if (object->free_count > 0)
|
||||
{
|
||||
swRingBuffer_collect(object);
|
||||
}
|
||||
|
||||
if (object->status == 0)
|
||||
{
|
||||
if (object->alloc_offset + alloc_size >= (object->size - sizeof(swRingBuffer_item)))
|
||||
{
|
||||
uint32_t skip_n = object->size - object->alloc_offset;
|
||||
if (skip_n >= sizeof(swRingBuffer_item))
|
||||
{
|
||||
item = object->memory + object->alloc_offset;
|
||||
item->lock = 0;
|
||||
item->length = skip_n - sizeof(swRingBuffer_item);
|
||||
sw_atomic_t *free_count = &object->free_count;
|
||||
sw_atomic_fetch_add(free_count, 1);
|
||||
}
|
||||
object->alloc_offset = 0;
|
||||
object->status = 1;
|
||||
capacity = object->collect_offset - object->alloc_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
capacity = object->size - object->alloc_offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
capacity = object->collect_offset - object->alloc_offset;
|
||||
}
|
||||
|
||||
if (capacity < alloc_size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item = object->memory + object->alloc_offset;
|
||||
item->lock = 1;
|
||||
item->length = size;
|
||||
item->index = object->alloc_count;
|
||||
|
||||
object->alloc_offset += alloc_size;
|
||||
object->alloc_count ++;
|
||||
|
||||
swDebug("alloc: ptr=%p", (void * )((void * )item->data - object->memory));
|
||||
|
||||
return item->data;
|
||||
}
|
||||
|
||||
static void swRingBuffer_free(swMemoryPool *pool, void *ptr)
|
||||
{
|
||||
swRingBuffer *object = pool->object;
|
||||
swRingBuffer_item *item = ptr - sizeof(swRingBuffer_item);
|
||||
|
||||
assert(ptr >= object->memory);
|
||||
assert(ptr <= object->memory + object->size);
|
||||
assert(item->lock == 1);
|
||||
|
||||
if (item->lock != 1)
|
||||
{
|
||||
swDebug("invalid free: index=%d, ptr=%p", item->index, (void * )((void * )item->data - object->memory));
|
||||
}
|
||||
else
|
||||
{
|
||||
item->lock = 0;
|
||||
}
|
||||
|
||||
swDebug("free: ptr=%p", (void * )((void * )item->data - object->memory));
|
||||
|
||||
sw_atomic_t *free_count = &object->free_count;
|
||||
sw_atomic_fetch_add(free_count, 1);
|
||||
}
|
||||
|
||||
static void swRingBuffer_destory(swMemoryPool *pool)
|
||||
{
|
||||
swRingBuffer *object = pool->object;
|
||||
if (object->shared)
|
||||
{
|
||||
sw_shm_free(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
sw_free(object);
|
||||
}
|
||||
}
|
178
vendor/swoole/src/memory/ShareMemory.c
vendored
Executable file
178
vendor/swoole/src/memory/ShareMemory.c
vendored
Executable file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include <sys/shm.h>
|
||||
|
||||
void* sw_shm_malloc(size_t size)
|
||||
{
|
||||
swShareMemory object;
|
||||
void *mem;
|
||||
size += sizeof(swShareMemory);
|
||||
mem = swShareMemory_mmap_create(&object, size, NULL);
|
||||
if (mem == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(mem, &object, sizeof(swShareMemory));
|
||||
return mem + sizeof(swShareMemory);
|
||||
}
|
||||
}
|
||||
|
||||
void* sw_shm_calloc(size_t num, size_t _size)
|
||||
{
|
||||
swShareMemory object;
|
||||
void *mem;
|
||||
void *ret_mem;
|
||||
int size = sizeof(swShareMemory) + (num * _size);
|
||||
mem = swShareMemory_mmap_create(&object, size, NULL);
|
||||
if (mem == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(mem, &object, sizeof(swShareMemory));
|
||||
ret_mem = mem + sizeof(swShareMemory);
|
||||
bzero(ret_mem, size - sizeof(swShareMemory));
|
||||
return ret_mem;
|
||||
}
|
||||
}
|
||||
|
||||
int sw_shm_protect(void *addr, int flags)
|
||||
{
|
||||
swShareMemory *object = (swShareMemory *) (addr - sizeof(swShareMemory));
|
||||
return mprotect(object, object->size, flags);
|
||||
}
|
||||
|
||||
void sw_shm_free(void *ptr)
|
||||
{
|
||||
swShareMemory *object = ptr - sizeof(swShareMemory);
|
||||
swShareMemory_mmap_free(object);
|
||||
}
|
||||
|
||||
void* sw_shm_realloc(void *ptr, size_t new_size)
|
||||
{
|
||||
swShareMemory *object = ptr - sizeof(swShareMemory);
|
||||
void *new_ptr;
|
||||
new_ptr = sw_shm_malloc(new_size);
|
||||
if (new_ptr == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(new_ptr, ptr, object->size);
|
||||
sw_shm_free(ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void *swShareMemory_mmap_create(swShareMemory *object, size_t size, char *mapfile)
|
||||
{
|
||||
void *mem;
|
||||
int tmpfd = -1;
|
||||
int flag = MAP_SHARED;
|
||||
bzero(object, sizeof(swShareMemory));
|
||||
|
||||
#ifdef MAP_ANONYMOUS
|
||||
flag |= MAP_ANONYMOUS;
|
||||
#else
|
||||
if (mapfile == NULL)
|
||||
{
|
||||
mapfile = "/dev/zero";
|
||||
}
|
||||
if ((tmpfd = open(mapfile, O_RDWR)) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
strncpy(object->mapfile, mapfile, SW_SHM_MMAP_FILE_LEN);
|
||||
object->tmpfd = tmpfd;
|
||||
#endif
|
||||
|
||||
#if defined(SW_USE_HUGEPAGE) && defined(MAP_HUGETLB)
|
||||
if (size > 2 * 1024 * 1024)
|
||||
{
|
||||
flag |= MAP_HUGETLB;
|
||||
}
|
||||
#endif
|
||||
|
||||
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flag, tmpfd, 0);
|
||||
#ifdef MAP_FAILED
|
||||
if (mem == MAP_FAILED)
|
||||
#else
|
||||
if (!mem)
|
||||
#endif
|
||||
{
|
||||
swWarn("mmap(%ld) failed. Error: %s[%d]", size, strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
object->size = size;
|
||||
object->mem = mem;
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
int swShareMemory_mmap_free(swShareMemory *object)
|
||||
{
|
||||
return munmap(object->mem, object->size);
|
||||
}
|
||||
|
||||
void *swShareMemory_sysv_create(swShareMemory *object, size_t size, int key)
|
||||
{
|
||||
int shmid;
|
||||
void *mem;
|
||||
bzero(object, sizeof(swShareMemory));
|
||||
|
||||
if (key == 0)
|
||||
{
|
||||
key = IPC_PRIVATE;
|
||||
}
|
||||
//SHM_R | SHM_W
|
||||
if ((shmid = shmget(key, size, IPC_CREAT)) < 0)
|
||||
{
|
||||
swSysError("shmget(%d, %ld) failed.", key, size);
|
||||
return NULL;
|
||||
}
|
||||
if ((mem = shmat(shmid, NULL, 0)) == (void *) -1)
|
||||
{
|
||||
swWarn("shmat() failed. Error: %s[%d]", strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
object->key = key;
|
||||
object->shmid = shmid;
|
||||
object->size = size;
|
||||
object->mem = mem;
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
int swShareMemory_sysv_free(swShareMemory *object, int rm)
|
||||
{
|
||||
int shmid = object->shmid;
|
||||
int ret = shmdt(object->mem);
|
||||
if (rm == 1)
|
||||
{
|
||||
shmctl(shmid, IPC_RMID, NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
483
vendor/swoole/src/memory/Table.c
vendored
Executable file
483
vendor/swoole/src/memory/Table.c
vendored
Executable file
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Swoole |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.0 of the Apache license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
||||
| If you did not receive a copy of the Apache2.0 license and are unable|
|
||||
| to obtain it through the world-wide-web, please send a note to |
|
||||
| license@swoole.com so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "swoole.h"
|
||||
#include "table.h"
|
||||
|
||||
//#define SW_TABLE_DEBUG 1
|
||||
#define SW_TABLE_USE_PHP_HASH
|
||||
|
||||
#ifdef SW_TABLE_DEBUG
|
||||
static int conflict_count = 0;
|
||||
static int insert_count = 0;
|
||||
static int conflict_max_level = 0;
|
||||
#endif
|
||||
|
||||
static void swTableColumn_free(swTableColumn *col);
|
||||
|
||||
static void swTableColumn_free(swTableColumn *col)
|
||||
{
|
||||
swString_free(col->name);
|
||||
sw_free(col);
|
||||
}
|
||||
|
||||
swTable* swTable_new(uint32_t rows_size, float conflict_proportion)
|
||||
{
|
||||
if (rows_size >= 0x80000000)
|
||||
{
|
||||
rows_size = 0x80000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t i = 10;
|
||||
while ((1U << i) < rows_size)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
rows_size = 1 << i;
|
||||
}
|
||||
|
||||
if (conflict_proportion > 1.0)
|
||||
{
|
||||
conflict_proportion = 1.0;
|
||||
}
|
||||
else if (conflict_proportion < SW_TABLE_CONFLICT_PROPORTION)
|
||||
{
|
||||
conflict_proportion = SW_TABLE_CONFLICT_PROPORTION;
|
||||
}
|
||||
|
||||
swTable *table = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(swTable));
|
||||
if (table == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (swMutex_create(&table->lock, 1) < 0)
|
||||
{
|
||||
swWarn("mutex create failed.");
|
||||
return NULL;
|
||||
}
|
||||
table->iterator = sw_malloc(sizeof(swTable_iterator));
|
||||
if (!table->iterator)
|
||||
{
|
||||
swWarn("malloc failed.");
|
||||
return NULL;
|
||||
}
|
||||
table->columns = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, (swHashMap_dtor)swTableColumn_free);
|
||||
if (!table->columns)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table->size = rows_size;
|
||||
table->mask = rows_size - 1;
|
||||
table->conflict_proportion = conflict_proportion;
|
||||
|
||||
bzero(table->iterator, sizeof(swTable_iterator));
|
||||
table->memory = NULL;
|
||||
return table;
|
||||
}
|
||||
|
||||
int swTableColumn_add(swTable *table, char *name, int len, int type, int size)
|
||||
{
|
||||
swTableColumn *col = sw_malloc(sizeof(swTableColumn));
|
||||
if (!col)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
col->name = swString_dup(name, len);
|
||||
if (!col->name)
|
||||
{
|
||||
sw_free(col);
|
||||
return SW_ERR;
|
||||
}
|
||||
switch(type)
|
||||
{
|
||||
case SW_TABLE_INT:
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
col->size = 1;
|
||||
col->type = SW_TABLE_INT8;
|
||||
break;
|
||||
case 2:
|
||||
col->size = 2;
|
||||
col->type = SW_TABLE_INT16;
|
||||
break;
|
||||
#ifdef __x86_64__
|
||||
case 8:
|
||||
col->size = 8;
|
||||
col->type = SW_TABLE_INT64;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
col->size = 4;
|
||||
col->type = SW_TABLE_INT32;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SW_TABLE_FLOAT:
|
||||
col->size = sizeof(double);
|
||||
col->type = SW_TABLE_FLOAT;
|
||||
break;
|
||||
case SW_TABLE_STRING:
|
||||
col->size = size + sizeof(swTable_string_length_t);
|
||||
col->type = SW_TABLE_STRING;
|
||||
break;
|
||||
default:
|
||||
swWarn("unkown column type.");
|
||||
swTableColumn_free(col);
|
||||
return SW_ERR;
|
||||
}
|
||||
col->index = table->item_size;
|
||||
table->item_size += col->size;
|
||||
table->column_num ++;
|
||||
return swHashMap_add(table->columns, name, len, col);
|
||||
}
|
||||
|
||||
size_t swTable_get_memory_size(swTable *table)
|
||||
{
|
||||
/**
|
||||
* table size + conflict size
|
||||
*/
|
||||
size_t row_num = table->size * (1 + table->conflict_proportion);
|
||||
|
||||
/*
|
||||
* header + data
|
||||
*/
|
||||
size_t row_memory_size = sizeof(swTableRow) + table->item_size;
|
||||
|
||||
/**
|
||||
* row data & header
|
||||
*/
|
||||
size_t memory_size = row_num * row_memory_size;
|
||||
|
||||
/**
|
||||
* memory pool for conflict rows
|
||||
*/
|
||||
memory_size += sizeof(swMemoryPool) + sizeof(swFixedPool) + ((row_num - table->size) * sizeof(swFixedPool_slice));
|
||||
|
||||
/**
|
||||
* for iterator, Iterate through all the elements
|
||||
*/
|
||||
memory_size += table->size * sizeof(swTableRow *);
|
||||
|
||||
return memory_size;
|
||||
}
|
||||
|
||||
int swTable_create(swTable *table)
|
||||
{
|
||||
size_t memory_size = swTable_get_memory_size(table);
|
||||
size_t row_memory_size = sizeof(swTableRow) + table->item_size;
|
||||
|
||||
void *memory = sw_shm_malloc(memory_size);
|
||||
if (memory == NULL)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
table->memory_size = memory_size;
|
||||
table->memory = memory;
|
||||
|
||||
table->rows = memory;
|
||||
memory += table->size * sizeof(swTableRow *);
|
||||
memory_size -= table->size * sizeof(swTableRow *);
|
||||
|
||||
#if SW_TABLE_USE_SPINLOCK == 0
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
|
||||
pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP);
|
||||
#endif
|
||||
|
||||
int i;
|
||||
for (i = 0; i < table->size; i++)
|
||||
{
|
||||
table->rows[i] = memory + (row_memory_size * i);
|
||||
memset(table->rows[i], 0, sizeof(swTableRow));
|
||||
#if SW_TABLE_USE_SPINLOCK == 0
|
||||
pthread_mutex_init(&table->rows[i]->lock, &attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
memory += row_memory_size * table->size;
|
||||
memory_size -= row_memory_size * table->size;
|
||||
table->pool = swFixedPool_new2(row_memory_size, memory, memory_size);
|
||||
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
void swTable_free(swTable *table)
|
||||
{
|
||||
#ifdef SW_TABLE_DEBUG
|
||||
printf("swoole_table: size=%d, conflict_count=%d, conflict_max_level=%d, insert_count=%d\n", table->size,
|
||||
conflict_count, conflict_max_level, insert_count);
|
||||
#endif
|
||||
|
||||
swHashMap_free(table->columns);
|
||||
sw_free(table->iterator);
|
||||
if (table->memory)
|
||||
{
|
||||
sw_shm_free(table->memory);
|
||||
}
|
||||
}
|
||||
|
||||
static sw_inline swTableRow* swTable_hash(swTable *table, char *key, int keylen)
|
||||
{
|
||||
#ifdef SW_TABLE_USE_PHP_HASH
|
||||
uint64_t hashv = swoole_hash_php(key, keylen);
|
||||
#else
|
||||
uint64_t hashv = swoole_hash_austin(key, keylen);
|
||||
#endif
|
||||
uint64_t index = hashv & table->mask;
|
||||
assert(index < table->size);
|
||||
return table->rows[index];
|
||||
}
|
||||
|
||||
void swTable_iterator_rewind(swTable *table)
|
||||
{
|
||||
bzero(table->iterator, sizeof(swTable_iterator));
|
||||
}
|
||||
|
||||
static sw_inline swTableRow* swTable_iterator_get(swTable *table, uint32_t index)
|
||||
{
|
||||
swTableRow *row = table->rows[index];
|
||||
return row->active ? row : NULL;
|
||||
}
|
||||
|
||||
swTableRow* swTable_iterator_current(swTable *table)
|
||||
{
|
||||
return table->iterator->row;
|
||||
}
|
||||
|
||||
void swTable_iterator_forward(swTable *table)
|
||||
{
|
||||
for (; table->iterator->absolute_index < table->size; table->iterator->absolute_index++)
|
||||
{
|
||||
swTableRow *row = swTable_iterator_get(table, table->iterator->absolute_index);
|
||||
if (row == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (row->next == NULL)
|
||||
{
|
||||
table->iterator->absolute_index++;
|
||||
table->iterator->row = row;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
for (;; i++)
|
||||
{
|
||||
if (row == NULL)
|
||||
{
|
||||
table->iterator->collision_index = 0;
|
||||
break;
|
||||
}
|
||||
if (i == table->iterator->collision_index)
|
||||
{
|
||||
table->iterator->collision_index++;
|
||||
table->iterator->row = row;
|
||||
return;
|
||||
}
|
||||
row = row->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
table->iterator->row = NULL;
|
||||
}
|
||||
|
||||
swTableRow* swTableRow_get(swTable *table, char *key, int keylen, swTableRow** rowlock)
|
||||
{
|
||||
if (keylen > SW_TABLE_KEY_SIZE)
|
||||
{
|
||||
keylen = SW_TABLE_KEY_SIZE;
|
||||
}
|
||||
|
||||
swTableRow *row = swTable_hash(table, key, keylen);
|
||||
*rowlock = row;
|
||||
swTableRow_lock(row);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (strncmp(row->key, key, keylen) == 0)
|
||||
{
|
||||
if (!row->active)
|
||||
{
|
||||
row = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (row->next == NULL)
|
||||
{
|
||||
row = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
row = row->next;
|
||||
}
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
swTableRow* swTableRow_set(swTable *table, char *key, int keylen, swTableRow **rowlock)
|
||||
{
|
||||
if (keylen > SW_TABLE_KEY_SIZE)
|
||||
{
|
||||
keylen = SW_TABLE_KEY_SIZE;
|
||||
}
|
||||
|
||||
swTableRow *row = swTable_hash(table, key, keylen);
|
||||
*rowlock = row;
|
||||
swTableRow_lock(row);
|
||||
|
||||
#ifdef SW_TABLE_DEBUG
|
||||
int _conflict_level = 0;
|
||||
#endif
|
||||
|
||||
if (row->active)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (strncmp(row->key, key, keylen) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (row->next == NULL)
|
||||
{
|
||||
table->lock.lock(&table->lock);
|
||||
swTableRow *new_row = table->pool->alloc(table->pool, 0);
|
||||
|
||||
#ifdef SW_TABLE_DEBUG
|
||||
conflict_count ++;
|
||||
if (_conflict_level > conflict_max_level)
|
||||
{
|
||||
conflict_max_level = _conflict_level;
|
||||
}
|
||||
|
||||
#endif
|
||||
table->lock.unlock(&table->lock);
|
||||
|
||||
if (!new_row)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
//add row_num
|
||||
bzero(new_row, sizeof(swTableRow));
|
||||
sw_atomic_fetch_add(&(table->row_num), 1);
|
||||
row->next = new_row;
|
||||
row = new_row;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
row = row->next;
|
||||
#ifdef SW_TABLE_DEBUG
|
||||
_conflict_level++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SW_TABLE_DEBUG
|
||||
insert_count ++;
|
||||
#endif
|
||||
sw_atomic_fetch_add(&(table->row_num), 1);
|
||||
}
|
||||
|
||||
memcpy(row->key, key, keylen);
|
||||
row->active = 1;
|
||||
return row;
|
||||
}
|
||||
|
||||
int swTableRow_del(swTable *table, char *key, int keylen)
|
||||
{
|
||||
if (keylen > SW_TABLE_KEY_SIZE)
|
||||
{
|
||||
keylen = SW_TABLE_KEY_SIZE;
|
||||
}
|
||||
|
||||
swTableRow *row = swTable_hash(table, key, keylen);
|
||||
//no exists
|
||||
if (!row->active)
|
||||
{
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
swTableRow_lock(row);
|
||||
if (row->next == NULL)
|
||||
{
|
||||
if (strncmp(row->key, key, keylen) == 0)
|
||||
{
|
||||
bzero(row, sizeof(swTableRow) + table->item_size);
|
||||
goto delete_element;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto not_exists;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
swTableRow *tmp = row;
|
||||
swTableRow *prev = NULL;
|
||||
|
||||
while (tmp)
|
||||
{
|
||||
if ((strncmp(tmp->key, key, keylen) == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if (tmp == NULL)
|
||||
{
|
||||
not_exists:
|
||||
swTableRow_unlock(row);
|
||||
return SW_ERR;
|
||||
}
|
||||
|
||||
//when the deleting element is root, we should move the first element's data to root,
|
||||
//and remove the element from the collision list.
|
||||
if (tmp == row)
|
||||
{
|
||||
tmp = tmp->next;
|
||||
row->next = tmp->next;
|
||||
memcpy(row->key, tmp->key, strlen(tmp->key));
|
||||
memcpy(row->data, tmp->data, table->item_size);
|
||||
}
|
||||
if (prev)
|
||||
{
|
||||
prev->next = tmp->next;
|
||||
}
|
||||
table->lock.lock(&table->lock);
|
||||
bzero(tmp, sizeof(swTableRow) + table->item_size);
|
||||
table->pool->free(table->pool, tmp);
|
||||
table->lock.unlock(&table->lock);
|
||||
}
|
||||
|
||||
delete_element:
|
||||
sw_atomic_fetch_sub(&(table->row_num), 1);
|
||||
swTableRow_unlock(row);
|
||||
|
||||
return SW_OK;
|
||||
}
|
Reference in New Issue
Block a user