From f6d28f11f9e03ba793ca95e9cfa6b697f1deff18 Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 28 Oct 2021 19:07:39 +0800 Subject: [PATCH 1/2] Fix link error for some compiler --- include/nostd/string_view.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/nostd/string_view.h b/include/nostd/string_view.h index 589fccae..0cc064d0 100644 --- a/include/nostd/string_view.h +++ b/include/nostd/string_view.h @@ -473,11 +473,9 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY basic_string_view { size_type length_; }; -#if !((defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)) template LIBATFRAME_UTILS_API_HEAD_ONLY constexpr const typename basic_string_view::size_type basic_string_view::npos; -#endif #if ((defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) # if defined(_MSC_VER) && _MSC_VER < 1920 From c68873e6676b96475f40036eab6f474da94f75bf Mon Sep 17 00:00:00 2001 From: owent Date: Thu, 28 Oct 2021 23:28:32 +0800 Subject: [PATCH 2/2] Fix timer --- CMakeLists.txt | 2 +- include/nostd/string_view.h | 3 +++ include/time/jiffies_timer.h | 30 ++++++++++++------------ test/case/time_test.cpp | 45 ++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89554710..a35cca26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ enable_testing() project( atframe_utils - VERSION "2.3.9" + VERSION "2.3.10" HOMEPAGE_URL "https://github.com/atframework/atframe_utils" LANGUAGES C CXX) diff --git a/include/nostd/string_view.h b/include/nostd/string_view.h index 0cc064d0..108992c1 100644 --- a/include/nostd/string_view.h +++ b/include/nostd/string_view.h @@ -473,9 +473,12 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY basic_string_view { size_type length_; }; +// https://en.cppreference.com/w/cpp/language/static +#if !((defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) template LIBATFRAME_UTILS_API_HEAD_ONLY constexpr const typename basic_string_view::size_type basic_string_view::npos; +#endif #if ((defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) # if defined(_MSC_VER) && _MSC_VER < 1920 diff --git a/include/time/jiffies_timer.h b/include/time/jiffies_timer.h index 38fae4f7..1f4286d0 100644 --- a/include/time/jiffies_timer.h +++ b/include/time/jiffies_timer.h @@ -147,6 +147,7 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY jiffies_timer { struct timer_flag_t { enum type { EN_JTTF_DISABLED = 0x0001, + EN_JTTF_REMOVED = 0x0002, // readonly flag }; }; @@ -192,7 +193,7 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY jiffies_timer { */ template inline int add_timer(time_t delta, TCALLBACK &&fn, void *priv_data, timer_wptr_t *watcher) { - return add_timer(delta, std::move(timer_callback_fn_t(std::forward(fn))), priv_data, watcher); + return add_timer(delta, timer_callback_fn_t(std::forward(fn)), priv_data, watcher); } int add_timer(time_t delta, timer_callback_fn_t &&fn, void *priv_data, timer_wptr_t *watcher) { @@ -261,7 +262,7 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY jiffies_timer { return error_type_t::EN_JTET_NOT_INITED; } - if (expires < last_tick_) { + if (expires <= last_tick_) { return ret; } @@ -273,11 +274,18 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY jiffies_timer { --list_sz; // 从高层级往低层级走,这样能保证定时器时序 - for (typename std::list::iterator iter = timer_list[list_sz]->begin(); - iter != timer_list[list_sz]->end();) { + if (timer_list[list_sz]->empty()) { + continue; + } + + typename std::list::iterator last_iter = timer_list[list_sz]->end(); + --last_iter; + bool consume_next = true; + for (typename std::list::iterator iter = timer_list[list_sz]->begin(); consume_next;) { // 在定时器回调函数中可能调用remove_timer来让当前迭代器失效 // 所以这里必须保存定时器智能指针,然后直接滚动到下一个,因为当前迭代器可能失效 timer_ptr_t timer_ptr = *iter; + consume_next = iter != last_iter; ++iter; if (timer_ptr) { if (timer_ptr->fn && !(timer_ptr->flags & timer_flag_t::EN_JTTF_DISABLED)) { @@ -285,19 +293,9 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY jiffies_timer { ++ret; } - if (nullptr != timer_ptr->owner_round) { - timer_ptr->owner_iter = timer_ptr->owner_round->end(); - timer_ptr->owner_round = nullptr; - } - - if (nullptr != timer_ptr->owner) { - --timer_ptr->owner->size_; - timer_ptr->owner = nullptr; - } + remove_timer(*timer_ptr); } } - - timer_list[list_sz]->clear(); } } @@ -377,6 +375,8 @@ class LIBATFRAME_UTILS_API_HEAD_ONLY jiffies_timer { --timer.owner->size_; timer.owner = nullptr; } + + set_timer_flags(timer, timer_flag_t::EN_JTTF_REMOVED); } private: diff --git a/test/case/time_test.cpp b/test/case/time_test.cpp index 7fe25593..53b24e3a 100644 --- a/test/case/time_test.cpp +++ b/test/case/time_test.cpp @@ -578,3 +578,48 @@ CASE_TEST(time_test, jiffies_timer_remove_in_callback) { // 重复调用remove_timer是安全的 short_timer_t::remove_timer(*timer_ptr); } + +struct jiffies_timer_add_in_callback_fn { + jiffies_timer_add_in_callback_fn() {} + + void operator()(time_t, const short_timer_t::timer_t &timer) { + CASE_MSG_INFO() << "jiffies_timer " << short_timer_t::get_timer_sequence(timer) << " add timer in callback" + << std::endl; + short_timer_t *owner = reinterpret_cast(short_timer_t::get_timer_private_data(timer)); + CASE_EXPECT_EQ(short_timer_t::error_type_t::EN_JTET_SUCCESS, + owner->add_timer(0, jiffies_timer_fn(nullptr), nullptr)); + CASE_EXPECT_EQ(short_timer_t::error_type_t::EN_JTET_SUCCESS, + owner->add_timer(short_timer_t::LVL_SIZE - 5 - 1, jiffies_timer_fn(nullptr), nullptr)); + CASE_EXPECT_EQ(short_timer_t::error_type_t::EN_JTET_SUCCESS, + owner->add_timer(short_timer_t::LVL_SIZE - 5, jiffies_timer_fn(nullptr), nullptr)); + CASE_EXPECT_EQ(short_timer_t::error_type_t::EN_JTET_SUCCESS, + owner->add_timer(short_timer_t::LVL_SIZE - 1, jiffies_timer_fn(nullptr), nullptr)); + CASE_EXPECT_EQ(short_timer_t::error_type_t::EN_JTET_SUCCESS, + owner->add_timer(short_timer_t::LVL_SIZE, jiffies_timer_fn(nullptr), nullptr)); + } +}; + +CASE_TEST(time_test, jiffies_timer_add_in_callback) { + short_timer_t short_timer; + time_t max_tick = short_timer.get_max_tick_distance() + 1; + short_timer_t::timer_wptr_t timer_holer; + short_timer_t::timer_ptr_t timer_ptr; + + CASE_EXPECT_EQ(short_timer_t::error_type_t::EN_JTET_SUCCESS, short_timer.init(max_tick)); + + CASE_EXPECT_EQ(short_timer_t::error_type_t::EN_JTET_SUCCESS, + short_timer.add_timer(5, jiffies_timer_add_in_callback_fn(), &short_timer, &timer_holer)); + CASE_EXPECT_EQ(1, static_cast(short_timer.size())); + + timer_ptr = timer_holer.lock(); + CASE_EXPECT_EQ(&short_timer, short_timer_t::get_timer_private_data(*timer_ptr)); + + short_timer.tick(max_tick + 6); + CASE_EXPECT_EQ(5, static_cast(short_timer.size())); + + short_timer.tick(max_tick + 6 + short_timer_t::LVL_SIZE); + CASE_EXPECT_EQ(1, static_cast(short_timer.size())); + + short_timer.tick(max_tick + 6 + short_timer_t::LVL_SIZE + short_timer_t::LVL_CLK_DIV); + CASE_EXPECT_EQ(0, static_cast(short_timer.size())); +}