From 0bfb542a0e60161915f0a50d06a025234b8b79b9 Mon Sep 17 00:00:00 2001 From: lixianjing Date: Mon, 18 Nov 2024 10:55:22 +0800 Subject: [PATCH] improve atomic --- docs/changes.md | 3 + src/tkc/atomic.h | 164 +++++++++++++++++++++++------------------- tests/atomic_test.cpp | 17 +++-- 3 files changed, 100 insertions(+), 84 deletions(-) diff --git a/docs/changes.md b/docs/changes.md index 3b87ae88c..f7b9dff30 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -1,5 +1,8 @@ # 最新动态 +2024/11/18 + * 完善 atomic(感谢兆坤提供补丁) + 2024/11/17 * 完善 TK_STRINGIZE(感谢兆坤提供补丁) * value完善调试log(感谢兆坤提供补丁) diff --git a/src/tkc/atomic.h b/src/tkc/atomic.h index 0f3f03cb9..c4cecfe67 100644 --- a/src/tkc/atomic.h +++ b/src/tkc/atomic.h @@ -60,6 +60,89 @@ static inline bool_t tk_atomic_support_value_type(value_type_t type) { } } +/** + * @method tk_atomic_deinit + * @export none + * 释放原子操作类对象。 + * + * @param {tk_atomic_t*} atomic 原子操作类对象。 + * + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +static ret_t tk_atomic_deinit(tk_atomic_t* atomic); + +/** + * @method tk_atomic_init + * @export none + * 初始化原子操作类对象。 + * + * @param {tk_atomic_t*} atomic 原子操作类对象。 + * @param {const value_t*} v 值。 + * + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +static ret_t tk_atomic_init(tk_atomic_t* atomic, const value_t* v); + +/** + * @method tk_atomic_exchange + * @export none + * 原子交换操作。 + * + * @param {const tk_atomic_t*} atomic 原子操作类对象。 + * @param {value_t*} v 交换值。 + * + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +static ret_t tk_atomic_exchange(tk_atomic_t* atomic, value_t* v); + +/** + * @method tk_atomic_store + * @export none + * 原子写操作。 + * + * @param {tk_atomic_t*} atomic 原子操作类对象。 + * @param {const value_t*} v 写入值。 + * + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +static ret_t tk_atomic_store(tk_atomic_t* atomic, const value_t* v); + +/** + * @method tk_atomic_load + * @export none + * 原子读操作。 + * + * @param {const tk_atomic_t*} atomic 原子操作类对象。 + * @param {value_t*} v 用于返回读取值。 + * + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +static ret_t tk_atomic_load(const tk_atomic_t* atomic, value_t* v); + +/** + * @method tk_atomic_fetch_add + * @export none + * 原子加操作。 + * + * @param {const tk_atomic_t*} atomic 原子操作类对象。 + * @param {value_t*} v 值。 + * + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +static ret_t tk_atomic_fetch_add(tk_atomic_t* atomic, value_t* v); + +/** + * @method tk_atomic_fetch_sub + * @export none + * 原子减操作。 + * + * @param {const tk_atomic_t*} atomic 原子操作类对象。 + * @param {value_t*} v 值。 + * + * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 + */ +static ret_t tk_atomic_fetch_sub(tk_atomic_t* atomic, value_t* v); + #if defined(WIN32) && !defined(MINGW) #include @@ -651,15 +734,6 @@ struct _tk_atomic_t { tk_mutex_t* lock; }; -/** - * @method tk_atomic_deinit - * @export none - * 释放原子操作类对象。 - * - * @param {tk_atomic_t*} atomic 原子操作类对象。 - * - * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 - */ static inline ret_t tk_atomic_deinit(tk_atomic_t* atomic) { ret_t ret = RET_OK; return_value_if_fail(atomic != NULL, RET_BAD_PARAMS); @@ -672,16 +746,6 @@ static inline ret_t tk_atomic_deinit(tk_atomic_t* atomic) { return ret; } -/** - * @method tk_atomic_init - * @export none - * 初始化原子操作类对象。 - * - * @param {tk_atomic_t*} atomic 原子操作类对象。 - * @param {const value_t*} v 值。 - * - * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 - */ static inline ret_t tk_atomic_init(tk_atomic_t* atomic, const value_t* v) { ret_t ret = RET_OK; return_value_if_fail(atomic != NULL && v != NULL, RET_BAD_PARAMS); @@ -699,43 +763,23 @@ static inline ret_t tk_atomic_init(tk_atomic_t* atomic, const value_t* v) { return ret; } -/** - * @method tk_atomic_exchange - * @export none - * 原子交换操作。 - * - * @param {const tk_atomic_t*} atomic 原子操作类对象。 - * @param {value_t*} v 交换值。 - * - * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 - */ static inline ret_t tk_atomic_exchange(tk_atomic_t* atomic, value_t* v) { ret_t ret = RET_OK; + value_t tmp; return_value_if_fail(atomic != NULL && v != NULL, RET_BAD_PARAMS); ret = tk_mutex_lock(atomic->lock); return_value_if_fail(RET_OK == ret, ret); /* 读-修改-写 */ - value_t tmp; value_copy(&tmp, &atomic->value); ret = value_copy(&atomic->value, v); value_copy(v, &tmp); -error: + tk_mutex_unlock(atomic->lock); return ret; } -/** - * @method tk_atomic_store - * @export none - * 原子写操作。 - * - * @param {tk_atomic_t*} atomic 原子操作类对象。 - * @param {const value_t*} v 写入值。 - * - * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 - */ static inline ret_t tk_atomic_store(tk_atomic_t* atomic, const value_t* v) { ret_t ret = RET_OK; return_value_if_fail(atomic != NULL && v != NULL, RET_BAD_PARAMS); @@ -744,21 +788,11 @@ static inline ret_t tk_atomic_store(tk_atomic_t* atomic, const value_t* v) { return_value_if_fail(RET_OK == ret, ret); ret = value_copy(&atomic->value, v); -error: + tk_mutex_unlock(atomic->lock); return ret; } -/** - * @method tk_atomic_load - * @export none - * 原子读操作。 - * - * @param {const tk_atomic_t*} atomic 原子操作类对象。 - * @param {value_t*} v 用于返回读取值。 - * - * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 - */ static inline ret_t tk_atomic_load(const tk_atomic_t* atomic, value_t* v) { ret_t ret = RET_OK; return_value_if_fail(atomic != NULL && v != NULL, RET_BAD_PARAMS); @@ -767,21 +801,11 @@ static inline ret_t tk_atomic_load(const tk_atomic_t* atomic, value_t* v) { return_value_if_fail(RET_OK == ret, ret); ret = value_copy(v, &atomic->value); -error: + tk_mutex_unlock(atomic->lock); return ret; } -/** - * @method tk_atomic_fetch_add - * @export none - * 原子加操作。 - * - * @param {const tk_atomic_t*} atomic 原子操作类对象。 - * @param {value_t*} v 值。 - * - * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 - */ static inline ret_t tk_atomic_fetch_add(tk_atomic_t* atomic, value_t* v) { ret_t ret = RET_OK; return_value_if_fail(atomic != NULL && v != NULL, RET_BAD_PARAMS); @@ -790,21 +814,11 @@ static inline ret_t tk_atomic_fetch_add(tk_atomic_t* atomic, value_t* v) { return_value_if_fail(RET_OK == ret, ret); ret = value_add(&atomic->value, v, &atomic->value); -error: + tk_mutex_unlock(atomic->lock); return ret; } -/** - * @method tk_atomic_fetch_sub - * @export none - * 原子减操作。 - * - * @param {const tk_atomic_t*} atomic 原子操作类对象。 - * @param {value_t*} v 值。 - * - * @return {ret_t} 返回RET_OK表示成功,否则表示失败。 - */ static inline ret_t tk_atomic_fetch_sub(tk_atomic_t* atomic, value_t* v) { ret_t ret = RET_OK; return_value_if_fail(atomic != NULL && v != NULL, RET_BAD_PARAMS); @@ -813,7 +827,7 @@ static inline ret_t tk_atomic_fetch_sub(tk_atomic_t* atomic, value_t* v) { return_value_if_fail(RET_OK == ret, ret); ret = value_sub(&atomic->value, v, &atomic->value); -error: + tk_mutex_unlock(atomic->lock); return ret; } diff --git a/tests/atomic_test.cpp b/tests/atomic_test.cpp index 148f59320..2d15a724c 100644 --- a/tests/atomic_test.cpp +++ b/tests/atomic_test.cpp @@ -12,7 +12,6 @@ static tk_atomic_t s_atomic; static void* inc_thread(void* args) { - uint32_t id = (uint32_t)tk_pointer_to_int(args); uint64_t i = 0; value_t v; @@ -26,7 +25,6 @@ static void* inc_thread(void* args) { } static void* dec_thread(void* args) { - uint32_t id = (uint32_t)tk_pointer_to_int(args); uint64_t i = 0; value_t v; @@ -62,13 +60,13 @@ int main(int argc, char* argv[]) { platform_prepare(); timer_prepare(time_now_ms); - tk_atomic_init(&s_atomic, value_set_int(&v, 0)); + tk_atomic_init(&s_atomic, value_set_uint64(&v, 0)); for (i = 0; i < ARRAY_SIZE(entrys); i++) { uint32_t j = 0; value_t tmp; - log_debug("entrys[%u] start\n", i); + log_debug("entrys[%" PRIu32 "] start\n", i); tk_atomic_store(&s_atomic, value_set_uint64(&v, entrys_init_value[i])); @@ -82,7 +80,7 @@ int main(int argc, char* argv[]) { for (j = 0; j < ARRAY_SIZE(threads); j++) { tk_thread_join(threads[j]); tk_thread_destroy(threads[j]); - log_debug("%u stop\n", j); + log_debug("%" PRIu32 " stop\n", j); } entrys_time[i] = timer_manager()->get_time() - entrys_time[i]; @@ -90,7 +88,7 @@ int main(int argc, char* argv[]) { tk_atomic_load(&s_atomic, &tmp); entrys_result[i] = value_uint64(&tmp); - log_debug("entrys[%u] result %llu\n", i, entrys_result[i]); + log_debug("entrys[%" PRIu32 "] result %" PRIu64 "\n", i, entrys_result[i]); } tk_atomic_deinit(&s_atomic); @@ -98,12 +96,13 @@ int main(int argc, char* argv[]) { log_debug("\n"); for (i = 0; i < ARRAY_SIZE(entrys); i++) { - log_debug("entrys[%u] : time = %llu ms, result = %llu, correct = %s\n", i, entrys_time[i], - entrys_result[i], entrys_result[i] == entrys_correct[i] ? "True" : "False"); + log_debug("entrys[%" PRIu32 "] : time = %" PRIu64 " ms, result = %" PRIu64 ", correct = %s\n", + i, entrys_time[i], entrys_result[i], + entrys_result[i] == entrys_correct[i] ? "True" : "False"); total_time += entrys_time[i]; } - log_debug("\ntotal time = %llu ms\n", total_time); + log_debug("\ntotal time = %" PRIu64 " ms\n", total_time); return 0; }