diff --git a/HISTORY b/HISTORY index ccf2fdb..e915ad3 100644 --- a/HISTORY +++ b/HISTORY @@ -1,11 +1,12 @@ -Version 1.54 2021-09-10 +Version 1.54 2021-09-13 * fast_allocator.[hc]: correct reclaim_interval logic * shared_func.[hc]: add functions getFileContentEx1 and getFileContent1 * fc_queue.[hc]: add function fc_queue_timedpeek * pthread_func.[hc]: add function init_pthread_rwlock * add files: sorted_queue.[hc] * add files: array_allocator.[hc] + * add files: sorted_array.[hc] Version 1.53 2021-06-30 * process_action support action status diff --git a/src/Makefile.in b/src/Makefile.in index 0565c30..74a09fc 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -17,7 +17,7 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \ multi_socket_client.lo skiplist_set.lo uniq_skiplist.lo \ json_parser.lo buffered_file_writer.lo server_id_func.lo \ fc_queue.lo sorted_queue.lo fc_memory.lo shared_buffer.lo \ - thread_pool.lo array_allocator.lo + thread_pool.lo array_allocator.lo sorted_array.lo FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ logger.o sockopt.o base64.o sched_thread.o \ @@ -31,7 +31,7 @@ FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ multi_socket_client.o skiplist_set.o uniq_skiplist.o \ json_parser.o buffered_file_writer.o server_id_func.o \ fc_queue.o sorted_queue.o fc_memory.o shared_buffer.o \ - thread_pool.o array_allocator.o + thread_pool.o array_allocator.o sorted_array.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 \ @@ -46,7 +46,8 @@ HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \ multi_socket_client.h skiplist_set.h uniq_skiplist.h \ fc_list.h locked_list.h json_parser.h buffered_file_writer.h \ server_id_func.h fc_queue.h sorted_queue.h fc_memory.h \ - shared_buffer.h thread_pool.h fc_atomic.h array_allocator.h + shared_buffer.h thread_pool.h fc_atomic.h array_allocator.h \ + sorted_array.h ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS) diff --git a/src/array_allocator.c b/src/array_allocator.c index 57dc2b7..9af926f 100644 --- a/src/array_allocator.c +++ b/src/array_allocator.c @@ -71,3 +71,46 @@ VoidArray *array_allocator_alloc(ArrayAllocatorContext *ctx, bytes = sizeof(VoidArray) + alloc * ctx->element_size; return (VoidArray *)fast_allocator_alloc(&ctx->allocator, bytes); } + +VoidArray *array_allocator_realloc(ArrayAllocatorContext *ctx, + VoidArray *old_array, const int target_count) +{ + VoidArray *new_array; + + if (old_array == NULL) { + return array_allocator_alloc(ctx, target_count); + } + + if (old_array->alloc >= target_count) { + return old_array; + } + + if ((new_array=array_allocator_alloc(ctx, target_count)) != NULL) { + if (old_array->count > 0) { + memcpy(new_array->elts, old_array->elts, ctx-> + element_size * old_array->count); + } + new_array->count = old_array->count; + } + + array_allocator_free(ctx, old_array); + return new_array; +} + +int array_compare_element_int64(const int64_t *n1, const int64_t *n2) +{ + int64_t sub; + sub = *n1 - *n2; + if (sub < 0) { + return -1; + } else if (sub > 0) { + return 1; + } else { + return 0; + } +} + +int array_compare_element_int32(const int32_t *n1, const int32_t *n2) +{ + return *n1 - *n2; +} diff --git a/src/array_allocator.h b/src/array_allocator.h index cc4946a..de6ff3a 100644 --- a/src/array_allocator.h +++ b/src/array_allocator.h @@ -39,7 +39,7 @@ typedef struct int32_t elts[0]; } I32Array; -typedef struct +typedef struct array_allocator_context { struct fast_allocator_context allocator; int element_size; @@ -57,6 +57,9 @@ extern "C" { VoidArray *array_allocator_alloc(ArrayAllocatorContext *ctx, const int target_count); + VoidArray *array_allocator_realloc(ArrayAllocatorContext *ctx, + VoidArray *old_array, const int target_count); + static inline void array_allocator_free(ArrayAllocatorContext *ctx, VoidArray *array) { @@ -64,6 +67,9 @@ extern "C" { fast_allocator_free(&ctx->allocator, array); } + int array_compare_element_int64(const int64_t *n1, const int64_t *n2); + + int array_compare_element_int32(const int32_t *n1, const int32_t *n2); #define i64_array_allocator_init(ctx, min_bits, max_bits) \ array_allocator_init(ctx, "i64", sizeof(int64_t), min_bits, max_bits) @@ -71,6 +77,9 @@ extern "C" { #define i64_array_allocator_alloc(ctx, target_count) \ (I64Array *)array_allocator_alloc(ctx, target_count) +#define i64_array_allocator_realloc(ctx, old_array, target_count) \ + (I64Array *)array_allocator_realloc(ctx, (VoidArray *)old_array, target_count) + #define i64_array_allocator_free(ctx, array) \ array_allocator_free(ctx, (VoidArray *)array) diff --git a/src/sorted_array.c b/src/sorted_array.c new file mode 100644 index 0000000..bde4822 --- /dev/null +++ b/src/sorted_array.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020 YuQing <384681@qq.com> + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include "sorted_array.h" + +void sorted_array_init(SortedArrayContext *ctx, + const int element_size, const bool allow_duplicate, + int (*compare_func)(const void *, const void *)) +{ + ctx->element_size = element_size; + ctx->allow_duplicate = allow_duplicate; + ctx->compare_func = compare_func; +} + +static void *sorted_array_bsearch(SortedArrayContext *ctx, void *base, + const int count, const void *element, int *insert_pos) +{ + int low; + int high; + int mid; + int compr; + + *insert_pos = 0; + low = 0; + high = count - 1; + while (low <= high) { + mid = (low + high) / 2; + compr = ctx->compare_func(base + mid, element); + if (compr < 0) { + low = mid + 1; + *insert_pos = low; + } else if (compr == 0) { + return base + mid; + } else { + high = mid - 1; + *insert_pos = mid; + } + } + + return NULL; +} + +int sorted_array_insert(SortedArrayContext *ctx, + void *base, int *count, const void *element) +{ + int insert_pos; + int move_count; + void *found; + void *end; + + found = sorted_array_bsearch(ctx, base, *count, element, &insert_pos); + if (found != NULL) { + if (!ctx->allow_duplicate) { + return EEXIST; + } + + found++; + end = base + *count; + while (found < end && ctx->compare_func(found, element) == 0) { + found++; + } + insert_pos = found - base; + } + + move_count = *count - insert_pos; + if (move_count > 0) { + memmove(base + insert_pos + 1, base + insert_pos, + ctx->element_size * move_count); + } + memcpy(base + insert_pos, element, ctx->element_size); + (*count)++; + return 0; +} + +int sorted_array_delete(SortedArrayContext *ctx, + void *base, int *count, const void *element) +{ + int move_count; + struct { + void *current; + void *start; + void *end; + } found; + void *array_end; + + if ((found.current=bsearch(element, base, *count, ctx->element_size, + ctx->compare_func)) == NULL) + { + return ENOENT; + } + + array_end = base + *count; + if (ctx->allow_duplicate) { + found.start = found.current; + while (found.start > base && ctx->compare_func( + found.start - 1, element) == 0) + { + found.start--; + } + + found.end = ++found.current; + while (found.end < array_end && ctx->compare_func( + found.end, element) == 0) + { + found.end++; + } + *count -= found.end - found.start; + } else { + found.start = found.current; + found.end = found.start + 1; + (*count)--; + } + + move_count = array_end - found.end; + if (move_count > 0) { + memmove(found.start, found.end, ctx-> + element_size * move_count); + } + return 0; +} + +int sorted_array_compare_int64(const int64_t *n1, const int64_t *n2) +{ + int64_t sub; + sub = *n1 - *n2; + if (sub < 0) { + return -1; + } else if (sub > 0) { + return 1; + } else { + return 0; + } +} + +int sorted_array_compare_int32(const int32_t *n1, const int32_t *n2) +{ + return *n1 - *n2; +} diff --git a/src/sorted_array.h b/src/sorted_array.h new file mode 100644 index 0000000..a2bb9e7 --- /dev/null +++ b/src/sorted_array.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 YuQing <384681@qq.com> + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef SORTED_ARRAY_H +#define SORTED_ARRAY_H + +#include "common_define.h" + +typedef struct sorted_array_context +{ + int element_size; + bool allow_duplicate; + int (*compare_func)(const void *, const void *); +} SortedArrayContext; + +#ifdef __cplusplus +extern "C" { +#endif + + void sorted_array_init(SortedArrayContext *ctx, + const int element_size, const bool allow_duplicate, + int (*compare_func)(const void *, const void *)); + + int sorted_array_insert(SortedArrayContext *ctx, + void *base, int *count, const void *element); + + int sorted_array_delete(SortedArrayContext *ctx, + void *base, int *count, const void *element); + + int sorted_array_compare_int64(const int64_t *n1, const int64_t *n2); + + int sorted_array_compare_int32(const int32_t *n1, const int32_t *n2); + + +#define sorted_i64_array_init(ctx, allow_duplicate) \ + sorted_array_init(ctx, sizeof(int64_t), allow_duplicate, \ + (int (*)(const void *, const void *))sorted_array_compare_int64) + +#define sorted_i32_array_init(ctx, allow_duplicate) \ + sorted_array_init(ctx, sizeof(int32_t), allow_duplicate, \ + (int (*)(const void *, const void *))sorted_array_compare_int32) + + +#ifdef __cplusplus +} +#endif + +#endif