made data structures immune to call term/destroy twice

This commit is contained in:
tezc 2021-04-13 22:16:30 +03:00
parent 3d11311f90
commit 57e67dc955
24 changed files with 223 additions and 124 deletions

View File

@ -2,9 +2,9 @@
Language: Cpp Language: Cpp
AccessModifierOffset: -4 AccessModifierOffset: -4
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: None
AlignConsecutiveDeclarations: false AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: true AlignConsecutiveMacros: None
AlignEscapedNewlines: Right AlignEscapedNewlines: Right
AlignOperands: Align AlignOperands: Align
AlignTrailingComments: true AlignTrailingComments: true
@ -100,7 +100,7 @@ PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right PointerAlignment: Right
ReflowComments: true ReflowComments: true
SortIncludes: true SortIncludes: CaseSensitive
SortUsingDeclarations: true SortUsingDeclarations: true
SpaceAfterCStyleCast: true SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true

View File

@ -46,6 +46,11 @@ static void test1(void)
{ {
int *arr, total = 0; int *arr, total = 0;
sc_array_create(arr, 10);
assert(arr != NULL);
sc_array_destroy(arr);
assert(arr == NULL);
sc_array_create(arr, 5); sc_array_create(arr, 5);
sc_array_add(arr, 3); sc_array_add(arr, 3);
sc_array_add(arr, 4); sc_array_add(arr, 4);

View File

@ -9,6 +9,24 @@ void test1()
const char *xstr; const char *xstr;
struct sc_buf buf, buf2; struct sc_buf buf, buf2;
sc_buf_init(&buf, 100);
assert(buf.mem != NULL);
sc_buf_term(&buf);
sc_buf_init(&buf2, 0);
assert(buf.mem == buf2.mem);
assert(buf.limit == buf2.limit);
assert(buf.wpos == buf2.wpos);
assert(buf.rpos == buf2.rpos);
assert(buf.ref == buf2.ref);
assert(buf.cap == buf2.cap);
assert(buf.err == buf2.err);
sc_buf_term(&buf2);
sc_buf_put_64(&buf, 100);
assert(sc_buf_get_64(&buf) == 100);
sc_buf_term(&buf);
sc_buf_init(&buf, 100); sc_buf_init(&buf, 100);
sc_buf_set_rpos(&buf, 1); sc_buf_set_rpos(&buf, 1);
assert(sc_buf_valid(&buf) == false); assert(sc_buf_valid(&buf) == false);

View File

@ -69,6 +69,8 @@ void sc_buf_term(struct sc_buf *b)
if (!b->ref) { if (!b->ref) {
sc_buf_free(b->mem); sc_buf_free(b->mem);
} }
sc_buf_init(b, 0);
} }
void sc_buf_limit(struct sc_buf *b, uint32_t limit) void sc_buf_limit(struct sc_buf *b, uint32_t limit)

View File

@ -113,16 +113,17 @@ int sc_thread_start(struct sc_thread *thread, void *(*fn)(void *), void *arg)
int sc_thread_join(struct sc_thread *thread, void **ret) int sc_thread_join(struct sc_thread *thread, void **ret)
{ {
int rc; int rc = 0;
void *val; void *val = NULL;
if (thread->id == 0) { if (thread->id == 0) {
return -1; goto out;
} }
rc = pthread_join(thread->id, &val); rc = pthread_join(thread->id, &val);
thread->id = 0; thread->id = 0;
out:
if (ret != NULL) { if (ret != NULL) {
*ret = val; *ret = val;
} }

View File

@ -4,6 +4,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
int example(void) int example(void)
{ {
@ -54,6 +55,19 @@ void test1(void)
void *data; void *data;
struct sc_heap heap; struct sc_heap heap;
sc_heap_init(&heap, 0);
sc_heap_add(&heap, 100, "test");
sc_heap_pop(&heap, &key, &data);
assert(key == 100);
assert(strcmp("test", data) == 0);
sc_heap_term(&heap);
sc_heap_add(&heap, 100, "test");
sc_heap_pop(&heap, &key, &data);
assert(key == 100);
assert(strcmp("test", data) == 0);
sc_heap_term(&heap);
assert(sc_heap_init(&heap, SIZE_MAX / 2) == false); assert(sc_heap_init(&heap, SIZE_MAX / 2) == false);
assert(sc_heap_init(&heap, 3) == true); assert(sc_heap_init(&heap, 3) == true);
@ -67,7 +81,7 @@ void test1(void)
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
assert(sc_heap_add(&heap, arr[i], assert(sc_heap_add(&heap, arr[i],
(void *) (uintptr_t)(arr[i] * 2)) == true); (void *) (uintptr_t) (arr[i] * 2)) == true);
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
@ -97,7 +111,7 @@ void test2(void)
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
assert(sc_heap_add(&heap, -arr[i], assert(sc_heap_add(&heap, -arr[i],
(void *) (uintptr_t)(arr[i] * 2)) == true); (void *) (uintptr_t) (arr[i] * 2)) == true);
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {

View File

@ -54,6 +54,10 @@ bool sc_heap_init(struct sc_heap *h, size_t cap)
void sc_heap_term(struct sc_heap *h) void sc_heap_term(struct sc_heap *h)
{ {
sc_heap_free(h->elems); sc_heap_free(h->elems);
*h = (struct sc_heap){
.elems = NULL,
};
} }
size_t sc_heap_size(struct sc_heap *h) size_t sc_heap_size(struct sc_heap *h)

View File

@ -29,7 +29,6 @@
#include "sc_ini.h" #include "sc_ini.h"
#include <ctype.h> #include <ctype.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)

View File

@ -186,9 +186,12 @@ int sc_log_term(void)
if (rc != 0) { if (rc != 0) {
rc = -1; rc = -1;
} }
sc_log_mutex_term(&sc_log.mtx);
} }
sc_log_mutex_term(&sc_log.mtx); sc_log = (struct sc_log){
.fp = NULL,
};
return rc; return rc;
} }

View File

@ -518,6 +518,17 @@ void test1()
values[i] = str_random((rand() % 64) + 32); values[i] = str_random((rand() % 64) + 32);
} }
sc_map_init_str(&map, 0, 0);
sc_map_put_str(&map, "100", "200");
sc_map_get_str(&map, "100", &value);
assert(strcmp(value, "200") == 0);
sc_map_term_str(&map);
sc_map_put_str(&map, "100", "200");
sc_map_get_str(&map, "100", &value);
assert(strcmp(value, "200") == 0);
sc_map_term_str(&map);
assert(!sc_map_init_str(&map, 0, -1)); assert(!sc_map_init_str(&map, 0, -1));
assert(!sc_map_init_str(&map, 0, 24)); assert(!sc_map_init_str(&map, 0, 24));
assert(!sc_map_init_str(&map, 0, 96)); assert(!sc_map_init_str(&map, 0, 96));

View File

@ -131,7 +131,7 @@
m->used = false; \ m->used = false; \
m->cap = cap; \ m->cap = cap; \
m->load_fac = f; \ m->load_fac = f; \
m->remap = (uint32_t)(m->cap * ((double) m->load_fac / 100)); \ m->remap = (uint32_t) (m->cap * ((double) m->load_fac / 100)); \
\ \
return true; \ return true; \
} \ } \
@ -140,6 +140,7 @@
{ \ { \
if (m->mem != sc_map_empty_##name.mem) { \ if (m->mem != sc_map_empty_##name.mem) { \
sc_map_free(&m->mem[-1]); \ sc_map_free(&m->mem[-1]); \
*m = sc_map_empty_##name; \
} \ } \
} \ } \
\ \
@ -199,7 +200,7 @@
\ \
m->mem = new; \ m->mem = new; \
m->cap = cap; \ m->cap = cap; \
m->remap = (uint32_t)(m->cap * ((double) m->load_fac / 100)); \ m->remap = (uint32_t) (m->cap * ((double) m->load_fac / 100)); \
\ \
return true; \ return true; \
} \ } \
@ -330,7 +331,7 @@ static uint32_t sc_map_hash_32(uint32_t a)
static uint32_t sc_map_hash_64(uint64_t a) static uint32_t sc_map_hash_64(uint64_t a)
{ {
return ((uint32_t) a) ^ (uint32_t)(a >> 32u); return ((uint32_t) a) ^ (uint32_t) (a >> 32u);
} }
// clang-format off // clang-format off

View File

@ -21,6 +21,8 @@ void test1()
assert(rc == 0); assert(rc == 0);
rc = sc_mmap_term(&mmap); rc = sc_mmap_term(&mmap);
assert(rc == 0); assert(rc == 0);
rc = sc_mmap_term(&mmap);
assert(rc == 0);
rc = sc_mmap_init(&mmap, "x.txt", O_RDWR | O_CREAT | O_TRUNC, rc = sc_mmap_init(&mmap, "x.txt", O_RDWR | O_CREAT | O_TRUNC,
PROT_READ | PROT_WRITE, MAP_SHARED, 0, 8192); PROT_READ | PROT_WRITE, MAP_SHARED, 0, 8192);

View File

@ -261,6 +261,10 @@ int sc_mmap_term(struct sc_mmap *m)
{ {
int rc; int rc;
if (m->fd == -1) {
return 0;
}
close(m->fd); close(m->fd);
rc = munmap(m->ptr, m->len); rc = munmap(m->ptr, m->len);
@ -268,6 +272,12 @@ int sc_mmap_term(struct sc_mmap *m)
strncpy(m->err, strerror(errno), sizeof(m->err) - 1); strncpy(m->err, strerror(errno), sizeof(m->err) - 1);
} }
*m = (struct sc_mmap) {
.ptr = NULL,
.fd = -1,
.len = 0,
};
return rc; return rc;
} }

View File

@ -135,13 +135,14 @@ char *sc_str_create_fmt(const char *fmt, ...)
return str; return str;
} }
void sc_str_destroy(char *str) void sc_str_destroy(char **str)
{ {
if (str == NULL) { if (str == NULL || *str == NULL) {
return; return;
} }
sc_str_free(sc_str_meta(str)); sc_str_free(sc_str_meta(*str));
*str = NULL;
} }
int64_t sc_str_len(const char *str) int64_t sc_str_len(const char *str)
@ -174,7 +175,7 @@ bool sc_str_set(char **str, const char *param)
return false; return false;
} }
sc_str_destroy(*str); sc_str_destroy(str);
*str = c; *str = c;
return true; return true;
@ -190,7 +191,7 @@ bool sc_str_set_fmt(char **str, const char *fmt, ...)
va_end(args); va_end(args);
if (ret != NULL) { if (ret != NULL) {
sc_str_destroy(*str); sc_str_destroy(str);
*str = ret; *str = ret;
} }
@ -310,7 +311,7 @@ bool sc_str_trim(char **str, const char *list)
return false; return false;
} }
sc_str_destroy(*str); sc_str_destroy(str);
*str = head; *str = head;
} }
@ -336,7 +337,7 @@ bool sc_str_substring(char **str, uint32_t start, uint32_t end)
return false; return false;
} }
sc_str_destroy(*str); sc_str_destroy(str);
*str = c; *str = c;
return true; return true;
@ -416,7 +417,7 @@ bool sc_str_replace(char **str, const char *replace, const char *with)
memcpy(tmp, orig, orig_end - orig + 1); memcpy(tmp, orig, orig_end - orig + 1);
sc_str_destroy(*str); sc_str_destroy(str);
*str = dest->buf; *str = dest->buf;
return true; return true;

View File

@ -82,7 +82,7 @@ char *sc_str_create_va(const char *fmt, va_list va);
* Deallocate length prefixed string. * Deallocate length prefixed string.
* @param str length prefixed string. str may be NULL. * @param str length prefixed string. str may be NULL.
*/ */
void sc_str_destroy(char *str); void sc_str_destroy(char **str);
/** /**
* @param str length prefixed string. NULL values are accepted. * @param str length prefixed string. NULL values are accepted.

View File

@ -62,6 +62,13 @@ int __wrap_vsnprintf(char *str, size_t size, const char *format, va_list ap)
void test1() void test1()
{ {
char* m = sc_str_create(NULL);
sc_str_destroy(&m);
sc_str_append(&m, "test");
sc_str_append_fmt(&m, "%d", 3);
assert(strcmp(m, "test3") == 0);
sc_str_destroy(&m);
assert(sc_str_len(NULL) == -1); assert(sc_str_len(NULL) == -1);
sc_str_destroy(NULL); sc_str_destroy(NULL);
assert(sc_str_dup(NULL) == NULL); assert(sc_str_dup(NULL) == NULL);
@ -79,8 +86,8 @@ void test1()
assert(strcmp(s1, "test3") == 0); assert(strcmp(s1, "test3") == 0);
fail_malloc = false; fail_malloc = false;
sc_str_destroy(s1); sc_str_destroy(&s1);
sc_str_destroy(s2); sc_str_destroy(&s2);
fail_malloc = true; fail_malloc = true;
assert(sc_str_create("test") == NULL); assert(sc_str_create("test") == NULL);
@ -96,8 +103,8 @@ void test1()
assert(strcmp(s1, "5test5") == 0); assert(strcmp(s1, "5test5") == 0);
s2 = sc_str_dup(s1); s2 = sc_str_dup(s1);
assert(sc_str_cmp(s1, s2) == true); assert(sc_str_cmp(s1, s2) == true);
sc_str_destroy(s1); sc_str_destroy(&s1);
sc_str_destroy(s2); sc_str_destroy(&s2);
fail_malloc = true; fail_malloc = true;
s1 = sc_str_create_fmt("%dtest%d", 5, 5); s1 = sc_str_create_fmt("%dtest%d", 5, 5);
@ -152,7 +159,7 @@ void test1()
assert(strcmp(s1, "test") == 0); assert(strcmp(s1, "test") == 0);
fail_vsnprintf_at = -1; fail_vsnprintf_at = -1;
free(s2); free(s2);
sc_str_destroy(s1); sc_str_destroy(&s1);
fail_vsnprintf = true; fail_vsnprintf = true;
assert(!sc_str_set_fmt(&s1, "test%d", 3)); assert(!sc_str_set_fmt(&s1, "test%d", 3));
@ -201,7 +208,7 @@ void test2()
fail_strlen = 2; fail_strlen = 2;
assert(sc_str_replace(&c, "*", "2") == false); assert(sc_str_replace(&c, "*", "2") == false);
fail_strlen = INT32_MAX; fail_strlen = INT32_MAX;
sc_str_destroy(c); sc_str_destroy(&c);
c = sc_str_create("n1n1"); c = sc_str_create("n1n1");
assert(sc_str_substring(&c, -1, -3) == false); assert(sc_str_substring(&c, -1, -3) == false);
@ -218,7 +225,7 @@ void test2()
assert(sc_str_append(&c, "12") == false); assert(sc_str_append(&c, "12") == false);
fail_realloc = false; fail_realloc = false;
sc_str_destroy(c); sc_str_destroy(&c);
fail_vsnprintf_at = 2; fail_vsnprintf_at = 2;
fail_vnsprintf_value = -1; fail_vnsprintf_value = -1;
@ -243,7 +250,7 @@ void test2()
assert(tmp[i] == x1[i]); assert(tmp[i] == x1[i]);
} }
sc_str_destroy(x1); sc_str_destroy(&x1);
free(tmp); free(tmp);
x1 = NULL; x1 = NULL;
@ -255,7 +262,7 @@ void test2()
assert(x1[i] == 'x'); assert(x1[i] == 'x');
} }
assert(sc_str_len(x1) == 4000); assert(sc_str_len(x1) == 4000);
sc_str_destroy(x1); sc_str_destroy(&x1);
} }
#endif #endif
@ -308,7 +315,7 @@ void test3()
while ((token = sc_str_token_begin(str, &save, "-")) != NULL) { while ((token = sc_str_token_begin(str, &save, "-")) != NULL) {
} }
sc_str_token_end(str, &save); sc_str_token_end(str, &save);
sc_str_destroy(str); sc_str_destroy(&str);
str = sc_str_create(NULL); str = sc_str_create(NULL);
save = NULL; save = NULL;
@ -316,12 +323,12 @@ void test3()
assert(strcmp(token, "token") == 0); assert(strcmp(token, "token") == 0);
} }
sc_str_token_end(str, &save); sc_str_token_end(str, &save);
sc_str_destroy(str); sc_str_destroy(&str);
str = sc_str_create("x,x"); str = sc_str_create("x,x");
save = NULL; save = NULL;
sc_str_token_end(str, &save); sc_str_token_end(str, &save);
sc_str_destroy(str); sc_str_destroy(&str);
str = sc_str_create("x,x"); str = sc_str_create("x,x");
save = NULL; save = NULL;
@ -330,7 +337,7 @@ void test3()
break; break;
} }
sc_str_token_end(str, &save); sc_str_token_end(str, &save);
sc_str_destroy(str); sc_str_destroy(&str);
str = sc_str_create("x,x"); str = sc_str_create("x,x");
save = NULL; save = NULL;
@ -340,7 +347,7 @@ void test3()
} }
sc_str_token_end(str, &save); sc_str_token_end(str, &save);
sc_str_token_end(str, &save); sc_str_token_end(str, &save);
sc_str_destroy(str); sc_str_destroy(&str);
} }
void test4() void test4()
@ -405,7 +412,7 @@ void test4()
sc_str_token_end(str, &save); sc_str_token_end(str, &save);
assert(strcmp(str, "tk1;tk2-tk3 tk4 tk5*tk6") == 0); assert(strcmp(str, "tk1;tk2-tk3 tk4 tk5*tk6") == 0);
sc_str_destroy(str); sc_str_destroy(&str);
} }
void test5() void test5()
@ -419,7 +426,7 @@ void test5()
assert(strcmp(s2, "test") == 0); assert(strcmp(s2, "test") == 0);
assert(sc_str_len(s2) == 4); assert(sc_str_len(s2) == 4);
assert(strcmp(s1, s2) == 0); assert(strcmp(s1, s2) == 0);
sc_str_destroy(s2); sc_str_destroy(&s2);
sc_str_set(&s1, "test2"); sc_str_set(&s1, "test2");
assert(strcmp(s1, "test2") == 0); assert(strcmp(s1, "test2") == 0);
@ -452,7 +459,7 @@ void test5()
assert(strcmp(s1, "longeRlongeR") == 0); assert(strcmp(s1, "longeRlongeR") == 0);
assert(sc_str_replace(&s1, "longeR", "")); assert(sc_str_replace(&s1, "longeR", ""));
assert(strcmp(s1, "") == 0); assert(strcmp(s1, "") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create("*test * test*"); s1 = sc_str_create("*test * test*");
sc_str_trim(&s1, "*"); sc_str_trim(&s1, "*");
@ -465,29 +472,29 @@ void test5()
sc_str_set(&s1, "testtx"); sc_str_set(&s1, "testtx");
sc_str_trim(&s1, "a"); sc_str_trim(&s1, "a");
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create(" elem1,elem2, elem3 "); s1 = sc_str_create(" elem1,elem2, elem3 ");
sc_str_trim(&s1, " "); sc_str_trim(&s1, " ");
assert(strcmp(s1, "elem1,elem2, elem3") == 0); assert(strcmp(s1, "elem1,elem2, elem3") == 0);
sc_str_replace(&s1, " ", ""); sc_str_replace(&s1, " ", "");
assert(strcmp(s1, "elem1,elem2,elem3") == 0); assert(strcmp(s1, "elem1,elem2,elem3") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create("elem1,elem2,elem3"); s1 = sc_str_create("elem1,elem2,elem3");
sc_str_replace(&s1, "elem", "item"); sc_str_replace(&s1, "elem", "item");
assert(strcmp(s1, "item1,item2,item3") == 0); assert(strcmp(s1, "item1,item2,item3") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create(NULL); s1 = sc_str_create(NULL);
assert(sc_str_append_fmt(&s1, "%s", "string") == true); assert(sc_str_append_fmt(&s1, "%s", "string") == true);
assert(strcmp(s1, "string") == 0); assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create(NULL); s1 = sc_str_create(NULL);
sc_str_append(&s1, "string"); sc_str_append(&s1, "string");
assert(strcmp(s1, "string") == 0); assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create(NULL); s1 = sc_str_create(NULL);
assert(sc_str_trim(&s1, "x") == true); assert(sc_str_trim(&s1, "x") == true);
@ -499,17 +506,17 @@ void test5()
assert(sc_str_dup(s1) == NULL); assert(sc_str_dup(s1) == NULL);
assert(sc_str_set(&s1, "string") == true); assert(sc_str_set(&s1, "string") == true);
assert(strcmp(s1, "string") == 0); assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create(NULL); s1 = sc_str_create(NULL);
assert(sc_str_set_fmt(&s1, "%s", "string") == true); assert(sc_str_set_fmt(&s1, "%s", "string") == true);
assert(strcmp(s1, "string") == 0); assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create(NULL); s1 = sc_str_create(NULL);
assert(sc_str_set(&s1, "string") == true); assert(sc_str_set(&s1, "string") == true);
assert(strcmp(s1, "string") == 0); assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
} }
void test6() void test6()
@ -521,47 +528,47 @@ void test6()
s1 = sc_str_create(NULL); s1 = sc_str_create(NULL);
assert(s1 == NULL); assert(s1 == NULL);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create_len(NULL, 100); s1 = sc_str_create_len(NULL, 100);
assert(s1 == NULL); assert(s1 == NULL);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = NULL; s1 = NULL;
b = sc_str_set(&s1, "test"); b = sc_str_set(&s1, "test");
assert(b); assert(b);
assert(strcmp(s1, "test") == 0); assert(strcmp(s1, "test") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = NULL; s1 = NULL;
b = sc_str_set_fmt(&s1, "test"); b = sc_str_set_fmt(&s1, "test");
assert(b); assert(b);
assert(strcmp(s1, "test") == 0); assert(strcmp(s1, "test") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = NULL; s1 = NULL;
b = sc_str_append(&s1, "test"); b = sc_str_append(&s1, "test");
assert(b); assert(b);
assert(strcmp(s1, "test") == 0); assert(strcmp(s1, "test") == 0);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = NULL; s1 = NULL;
b = sc_str_trim(&s1, "*"); b = sc_str_trim(&s1, "*");
assert(b); assert(b);
assert(s1 == NULL); assert(s1 == NULL);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = NULL; s1 = NULL;
b = sc_str_substring(&s1, 0, 0); b = sc_str_substring(&s1, 0, 0);
assert(!b); assert(!b);
assert(s1 == NULL); assert(s1 == NULL);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = NULL; s1 = NULL;
b = sc_str_replace(&s1, "s", "a"); b = sc_str_replace(&s1, "s", "a");
assert(b); assert(b);
assert(s1 == NULL); assert(s1 == NULL);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = NULL; s1 = NULL;
while ((token = sc_str_token_begin(s1, &save, ";")) != NULL) { while ((token = sc_str_token_begin(s1, &save, ";")) != NULL) {
@ -570,15 +577,15 @@ void test6()
} }
sc_str_token_end(s1, &save); sc_str_token_end(s1, &save);
sc_str_destroy(s1); sc_str_destroy(&s1);
s1 = sc_str_create("de1"); s1 = sc_str_create("de1");
s2 = sc_str_create("de2"); s2 = sc_str_create("de2");
assert(!sc_str_cmp(s1, s2)); assert(!sc_str_cmp(s1, s2));
sc_str_set(&s1, "dee2"); sc_str_set(&s1, "dee2");
assert(!sc_str_cmp(s1, s2)); assert(!sc_str_cmp(s1, s2));
sc_str_destroy(s1); sc_str_destroy(&s1);
sc_str_destroy(s2); sc_str_destroy(&s2);
} }
int main() int main()

View File

@ -78,12 +78,12 @@ int sc_thread_start(struct sc_thread *t, void *(*fn)(void *), void *arg)
int sc_thread_join(struct sc_thread *t, void **ret) int sc_thread_join(struct sc_thread *t, void **ret)
{ {
int rc = 0; int rc = 0;
void* val = NULL;
DWORD rv; DWORD rv;
BOOL brc; BOOL brc;
if (t->id == 0) { if (t->id == 0) {
strncpy(t->err, "Already stopped.", sizeof(t->err)); goto out;
return -1;
} }
rv = WaitForSingleObject(t->id, INFINITE); rv = WaitForSingleObject(t->id, INFINITE);
@ -98,7 +98,10 @@ int sc_thread_join(struct sc_thread *t, void **ret)
rc = -1; rc = -1;
} }
val = t->ret;
t->id = 0; t->id = 0;
out:
if (ret != NULL) { if (ret != NULL) {
*ret = t->ret; *ret = t->ret;
} }
@ -134,20 +137,17 @@ int sc_thread_start(struct sc_thread *t, void *(*fn)(void *), void *arg)
int sc_thread_join(struct sc_thread *t, void **ret) int sc_thread_join(struct sc_thread *t, void **ret)
{ {
int rc; int rc = 0;
void *val; void *val = NULL;
if (t->id == 0) { if (t->id == 0) {
return -1; goto out;
} }
rc = pthread_join(t->id, &val); rc = pthread_join(t->id, &val);
if (rc != 0) {
strncpy(t->err, strerror(rc), sizeof(t->err) - 1);
}
t->id = 0; t->id = 0;
out:
if (ret != NULL) { if (ret != NULL) {
*ret = val; *ret = val;
} }

View File

@ -26,7 +26,9 @@ void test1()
assert(strcmp((char *) ret, "first") == 0); assert(strcmp((char *) ret, "first") == 0);
rc = sc_thread_term(&thread); rc = sc_thread_term(&thread);
assert(rc == -1); assert(rc == 0);
rc = sc_thread_term(&thread);
assert(rc == 0);
sc_thread_init(&thread); sc_thread_init(&thread);
rc = sc_thread_start(&thread, fn, "first"); rc = sc_thread_start(&thread, fn, "first");

View File

@ -34,34 +34,20 @@
#define SC_TIMER_MAX (UINT32_MAX / sizeof(struct sc_timer_data)) / WHEEL_COUNT #define SC_TIMER_MAX (UINT32_MAX / sizeof(struct sc_timer_data)) / WHEEL_COUNT
#endif #endif
void sc_timer_init(struct sc_timer *t, uint64_t timestamp)
bool sc_timer_init(struct sc_timer *t, uint64_t timestamp)
{ {
const uint32_t wheel_cap = 4; *t = (struct sc_timer){
const uint32_t cap = WHEEL_COUNT * wheel_cap; .timestamp = timestamp,
const size_t size = cap * sizeof(struct sc_timer_data); };
t->count = 0;
t->head = 0;
t->wheel = wheel_cap;
t->timestamp = timestamp;
t->list = sc_timer_malloc(size);
if (t->list == NULL) {
return false;
}
for (uint32_t i = 0; i < cap; i++) {
t->list[i].timeout = UINT64_MAX;
t->list[i].data = NULL;
}
return true;
} }
void sc_timer_term(struct sc_timer *t) void sc_timer_term(struct sc_timer *t)
{ {
sc_timer_free(t->list); sc_timer_free(t->list);
*t = (struct sc_timer){
.timestamp = t->timestamp,
};
} }
void sc_timer_clear(struct sc_timer *t) void sc_timer_clear(struct sc_timer *t)
@ -79,7 +65,8 @@ void sc_timer_clear(struct sc_timer *t)
static bool expand(struct sc_timer *t) static bool expand(struct sc_timer *t)
{ {
uint32_t cap = t->wheel * WHEEL_COUNT * 2; uint32_t wheel = t->wheel != 0 ? t->wheel * 2 : 4;
uint32_t cap = wheel * WHEEL_COUNT * 2;
size_t size = cap * sizeof(struct sc_timer_data); size_t size = cap * sizeof(struct sc_timer_data);
struct sc_timer_data *alloc; struct sc_timer_data *alloc;
@ -111,7 +98,7 @@ static bool expand(struct sc_timer *t)
sc_timer_free(t->list); sc_timer_free(t->list);
t->list = alloc; t->list = alloc;
t->wheel *= 2; t->wheel = wheel;
return true; return true;
} }
@ -119,12 +106,11 @@ static bool expand(struct sc_timer *t)
uint64_t sc_timer_add(struct sc_timer *t, uint64_t timeout, uint64_t type, uint64_t sc_timer_add(struct sc_timer *t, uint64_t timeout, uint64_t type,
void *data) void *data)
{ {
const uint32_t offset = (uint32_t)(timeout / TICK + t->head); const uint32_t offset = (uint32_t) (timeout / TICK + t->head);
const uint32_t pos = offset & (WHEEL_COUNT - 1); const uint32_t pos = offset & (WHEEL_COUNT - 1);
uint64_t id; uint64_t id;
uint32_t seq, index, wheel_pos; uint32_t seq, index, wheel_pos;
wheel_pos = (pos * t->wheel); wheel_pos = (pos * t->wheel);
for (seq = 0; seq < t->wheel; seq++) { for (seq = 0; seq < t->wheel; seq++) {
index = wheel_pos + seq; index = wheel_pos + seq;
@ -176,7 +162,7 @@ uint64_t sc_timer_timeout(struct sc_timer *t, uint64_t timestamp, void *arg,
const uint64_t time = timestamp - t->timestamp; const uint64_t time = timestamp - t->timestamp;
uint32_t wheel, base; uint32_t wheel, base;
uint32_t head = t->head; uint32_t head = t->head;
uint32_t wheels = (uint32_t)(sc_timer_min(time / TICK, WHEEL_COUNT)); uint32_t wheels = (uint32_t) (sc_timer_min(time / TICK, WHEEL_COUNT));
struct sc_timer_data *item; struct sc_timer_data *item;
if (wheels == 0) { if (wheels == 0) {

View File

@ -60,9 +60,8 @@ struct sc_timer {
* *
* @param t timer * @param t timer
* @param timestamp current timestamp. Use monotonic timer source. * @param timestamp current timestamp. Use monotonic timer source.
* @return 'false' on out of memory.
*/ */
bool sc_timer_init(struct sc_timer *t, uint64_t timestamp); void sc_timer_init(struct sc_timer *t, uint64_t timestamp);
/** /**
* Destroy timer. * Destroy timer.

View File

@ -81,7 +81,8 @@ void test1(void)
{ {
struct sc_timer timer; struct sc_timer timer;
assert(sc_timer_init(&timer, time_ms())); sc_timer_init(&timer, time_ms());
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 100, i, ids[i] = sc_timer_add(&timer, rand() % 100, i,
(void *) (uintptr_t) i); (void *) (uintptr_t) i);
@ -105,13 +106,37 @@ void test1(void)
} }
sc_timer_term(&timer); sc_timer_term(&timer);
for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 100, i,
(void *) (uintptr_t) i);
assert(ids[i] != SC_TIMER_INVALID);
}
t = 10000;
while (t > 0) {
n = sc_timer_timeout(&timer, time_ms(),
(void *) (uintptr_t) 333, callback);
if (timer.count == 0) {
break;
}
t -= n;
sleep_ms(n);
}
for (int i = 0; i < 1000; i++) {
assert(ids[i] == SC_TIMER_INVALID);
}
sc_timer_term(&timer);
} }
void test2(void) void test2(void)
{ {
struct sc_timer timer; struct sc_timer timer;
assert(sc_timer_init(&timer, time_ms())); sc_timer_init(&timer, time_ms());
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
ids[i] = SC_TIMER_INVALID; ids[i] = SC_TIMER_INVALID;
sc_timer_add(&timer, rand() % 100, i, (void *) (uintptr_t) i); sc_timer_add(&timer, rand() % 100, i, (void *) (uintptr_t) i);
@ -164,7 +189,8 @@ void test3(void)
{ {
struct sc_timer timer; struct sc_timer timer;
assert(sc_timer_init(&timer, time_ms())); sc_timer_init(&timer, time_ms());
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 20, i, ids[i] = sc_timer_add(&timer, rand() % 20, i,
(void *) (uintptr_t) i); (void *) (uintptr_t) i);
@ -202,7 +228,8 @@ void test4(void)
{ {
struct sc_timer timer; struct sc_timer timer;
assert(sc_timer_init(&timer, 0)); sc_timer_init(&timer, 0);
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 20, i, ids[i] = sc_timer_add(&timer, rand() % 20, i,
(void *) (uintptr_t) i); (void *) (uintptr_t) i);
@ -256,10 +283,7 @@ void fail_test(void)
size_t max = 50000; size_t max = 50000;
struct sc_timer timer; struct sc_timer timer;
fail_malloc = true; sc_timer_init(&timer, time_ms());
assert(sc_timer_init(&timer, time_ms()) == false);
fail_malloc = false;
assert(sc_timer_init(&timer, time_ms()) == true);
uint64_t id; uint64_t id;
for (size_t i = 0; i < max + 100; i++) { for (size_t i = 0; i < max + 100; i++) {

View File

@ -174,7 +174,12 @@ error:
return NULL; return NULL;
} }
void sc_uri_destroy(struct sc_uri *uri) void sc_uri_destroy(struct sc_uri **uri)
{ {
sc_uri_free(uri); if (uri == NULL || *uri == NULL) {
return;
}
sc_uri_free(*uri);
*uri = NULL;
} }

View File

@ -100,6 +100,6 @@ struct sc_uri *sc_uri_create(const char *str);
/** /**
* @param uri uri * @param uri uri
*/ */
void sc_uri_destroy(struct sc_uri *uri); void sc_uri_destroy(struct sc_uri **uri);
#endif #endif

View File

@ -12,6 +12,11 @@ void test1(void)
const char *f = "foo://user:password@example.com:8042/over/" const char *f = "foo://user:password@example.com:8042/over/"
"there?name=ferret#nose"; "there?name=ferret#nose";
uri = sc_uri_create("");
assert(uri == NULL);
sc_uri_destroy(&uri);
sc_uri_destroy(NULL);
uri = sc_uri_create(f); uri = sc_uri_create(f);
assert(uri != NULL); assert(uri != NULL);
assert(strcmp(uri->str, f) == 0); assert(strcmp(uri->str, f) == 0);
@ -23,7 +28,7 @@ void test1(void)
assert(strcmp(uri->query, "name=ferret") == 0); assert(strcmp(uri->query, "name=ferret") == 0);
assert(strcmp(uri->fragment, "nose") == 0); assert(strcmp(uri->fragment, "nose") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test2(void) void test2(void)
@ -43,7 +48,7 @@ void test2(void)
assert(strcmp(uri->query, "tag=networking&order=newest") == 0); assert(strcmp(uri->query, "tag=networking&order=newest") == 0);
assert(strcmp(uri->fragment, "top") == 0); assert(strcmp(uri->fragment, "top") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test3(void) void test3(void)
@ -62,7 +67,7 @@ void test3(void)
assert(strcmp(uri->query, "objectClass?one") == 0); assert(strcmp(uri->query, "objectClass?one") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test4(void) void test4(void)
@ -81,7 +86,7 @@ void test4(void)
assert(strcmp(uri->query, "") == 0); assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test5(void) void test5(void)
@ -100,7 +105,7 @@ void test5(void)
assert(strcmp(uri->query, "") == 0); assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test6(void) void test6(void)
@ -119,7 +124,7 @@ void test6(void)
assert(strcmp(uri->query, "") == 0); assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test7(void) void test7(void)
@ -138,7 +143,7 @@ void test7(void)
assert(strcmp(uri->query, "") == 0); assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test8(void) void test8(void)
@ -158,7 +163,7 @@ void test8(void)
assert(strcmp(uri->query, "") == 0); assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test9(void) void test9(void)
@ -177,7 +182,7 @@ void test9(void)
assert(strcmp(uri->query, "fred") == 0); assert(strcmp(uri->query, "fred") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test10(void) void test10(void)
@ -196,7 +201,7 @@ void test10(void)
assert(strcmp(uri->query, "") == 0); assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0); assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test11(void) void test11(void)
@ -213,7 +218,7 @@ void test11(void)
NULL); NULL);
assert(sc_uri_create("ldap://[2001:db8::7") == NULL); assert(sc_uri_create("ldap://[2001:db8::7") == NULL);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test12(void) void test12(void)
@ -232,7 +237,7 @@ void test12(void)
assert(strcmp(uri->query, "x") == 0); assert(strcmp(uri->query, "x") == 0);
assert(strcmp(uri->fragment, "3") == 0); assert(strcmp(uri->fragment, "3") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
} }
void test13(void) void test13(void)
@ -321,13 +326,13 @@ void fail_test()
uri = sc_uri_create("tcp://127.0.0.1"); uri = sc_uri_create("tcp://127.0.0.1");
assert(uri != NULL); assert(uri != NULL);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
uri = sc_uri_create("tcp:/127.0.0.1"); uri = sc_uri_create("tcp:/127.0.0.1");
assert(uri != NULL); assert(uri != NULL);
assert(strcmp(uri->scheme, "tcp") == 0); assert(strcmp(uri->scheme, "tcp") == 0);
assert(strcmp(uri->path, "/127.0.0.1") == 0); assert(strcmp(uri->path, "/127.0.0.1") == 0);
sc_uri_destroy(uri); sc_uri_destroy(&uri);
fail_snprintf = -1; fail_snprintf = -1;
assert(sc_uri_create("tcp://127.0.0.1") == NULL); assert(sc_uri_create("tcp://127.0.0.1") == NULL);