feat add defer
Some checks failed
rpcrypto-build / build (Debug, himix200.toolchain.cmake) (push) Successful in 57s
rpcrypto-build / build (Debug, hisiv510.toolchain.cmake) (push) Failing after 14m46s
rpcrypto-build / build (Release, himix200.toolchain.cmake) (push) Failing after 14m48s
rpcrypto-build / build (Release, hisiv510.toolchain.cmake) (push) Failing after 14m51s
linux-hisiv500-gcc / linux-gcc-hisiv500 (push) Failing after 14m54s
linux-mips64-gcc / linux-gcc-mips64el (push) Failing after 14m57s
linux-x64-gcc / linux-gcc (push) Failing after 15m1s

This commit is contained in:
tqcq 2023-12-29 11:04:52 +08:00
parent 51f923757d
commit ce98a59397
4 changed files with 128 additions and 12 deletions

51
src/ulib/utils/defer.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef ULIB_SRC_ULIB_UTILS_DEFER_H_
#define ULIB_SRC_ULIB_UTILS_DEFER_H_
#include "ulib/base/noncopyable.h"
#include "ulib/base/stringize_macros.h"
#include <memory>
#include <algorithm>
#include <vector>
#include <functional>
namespace ulib {
class Defer : NonCopyable {
public:
using DeferFunc = std::function<void()>;
Defer() = default;
Defer(const DeferFunc &defer_func) { Add(defer_func); }
Defer(DeferFunc &&defer_func) { Add(std::move(defer_func)); }
Defer(Defer &&other) noexcept : defer_funcs_(std::move(other.defer_funcs_))
{}
~Defer()
{
std::for_each(defer_funcs_.rbegin(), defer_funcs_.rend(),
[](const DeferFunc &defer_func) { defer_func(); });
}
template<typename F, typename... Args>
void Add(F &&func, Args &&...args)
{
defer_funcs_.push_back(
std::bind(std::forward<F>(func), std::forward<Args>(args)...));
}
void Clear() { defer_funcs_.clear(); }
private:
std::vector<DeferFunc> defer_funcs_;
};
#define _ULIB_DEFER_CONCAT(a, b) a##b
#define ULIB_DEFER_CONCAT(a, b) _ULIB_DEFER_CONCAT(a, b)
#define defer(x) \
::ulib::Defer ULIB_DEFER_CONCAT(__ulib_defer__, __LINE__) = \
::ulib::Defer(x);
}// namespace ulib
#endif// ULIB_SRC_ULIB_UTILS_DEFER_H_

View File

@ -10,6 +10,7 @@ add_executable(ulib_test
ulib/system/thread_unittest.cpp ulib/system/thread_unittest.cpp
ulib/system/thread_pool_unittest.cpp ulib/system/thread_pool_unittest.cpp
ulib/system/timer_unittest.cpp ulib/system/timer_unittest.cpp
ulib/utils/defer_unittest.cpp
) )
target_link_libraries(ulib_test PRIVATE target_link_libraries(ulib_test PRIVATE
ulib ulib

View File

@ -7,30 +7,34 @@
class TimerTest : public ::testing::Test { class TimerTest : public ::testing::Test {
protected: protected:
void SetUp() override { latch_ = nullptr; } void SetUp() override { latch_ = nullptr; }
void TearDown() override { delete latch_; } void TearDown() override { delete latch_; }
protected: protected:
ulib::CountDownLatch *latch_; ulib::CountDownLatch *latch_;
}; };
TEST_F(TimerTest, OnceTrigger) { TEST_F(TimerTest, OnceTrigger)
{
latch_ = new ulib::CountDownLatch(1); latch_ = new ulib::CountDownLatch(1);
ulib::TimerId timer_id = ulib::TimerManager::AddTimer([&]{ ulib::TimerId timer_id =
latch_->CountDown(); ulib::TimerManager::AddTimer([&] { latch_->CountDown(); }, 1000);
}, 1000);
latch_->Await(); latch_->Await();
ulib::TimerManager::CancelTimer(timer_id); ulib::TimerManager::CancelTimer(timer_id);
} }
TEST_F(TimerTest, PeriodTrigger) { TEST_F(TimerTest, PeriodTrigger)
{
latch_ = new ulib::CountDownLatch(3); latch_ = new ulib::CountDownLatch(3);
std::atomic_int cnt(3); std::atomic_int cnt(3);
ulib::TimerId timer_id = ulib::TimerManager::AddTimer([&]{ ulib::TimerId timer_id = ulib::TimerManager::AddTimer(
[&] {
if (cnt.fetch_sub(1) > 0) { if (cnt.fetch_sub(1) > 0) {
ULOG_INFO("timer.unittest", "start count down: {}", cnt); ULOG_INFO("timer.unittest", "start count down: {}", cnt);
latch_->CountDown(); latch_->CountDown();
} }
}, 1000, 3000); },
1000, 1000);
latch_->Await(); latch_->Await();
ulib::TimerManager::CancelTimer(timer_id); ulib::TimerManager::CancelTimer(timer_id);
} }

View File

@ -0,0 +1,60 @@
#include <gtest/gtest.h>
#include <ulib/utils/defer.h>
TEST(Defer, Defer)
{
int i = 0;
{
defer([&i]() { i++; });
EXPECT_EQ(i, 0);
}
EXPECT_EQ(i, 1);
}
TEST(Defer, DeferFunc)
{
int i = 0;
{
defer([&i]() { i++; });
EXPECT_EQ(i, 0);
}
EXPECT_EQ(i, 1);
}
TEST(Defer, DeferMove)
{
int i = 0;
{
defer([&i]() { i++; });
EXPECT_EQ(i, 0);
defer([&i]() { i++; });
EXPECT_EQ(i, 0);
}
EXPECT_EQ(i, 2);
}
TEST(Defer, Add)
{
int i = 0;
{
ulib::Defer defer;
defer.Add([&i]() { i++; });
EXPECT_EQ(i, 0);
defer.Add([&i]() { i++; });
EXPECT_EQ(i, 0);
}
EXPECT_EQ(i, 2);
}
TEST(Defer, Clear)
{
int i = 0;
{
ulib::Defer defer;
defer.Add([&i]() { i++; });
EXPECT_EQ(i, 0);
defer.Clear();
EXPECT_EQ(i, 0);
}
EXPECT_EQ(i, 0);
}