From 1d6c040dcb9a01648edc66d8c0006c8c9294a705 Mon Sep 17 00:00:00 2001 From: lichao <lichao@aiotlink.com> Date: 星期四, 22 四月 2021 18:28:30 +0800 Subject: [PATCH] add mutex timeout limit; use atomic as refcount. --- utest/api_test.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 98 insertions(+), 4 deletions(-) diff --git a/utest/api_test.cpp b/utest/api_test.cpp index 7981a2c..a91db43 100644 --- a/utest/api_test.cpp +++ b/utest/api_test.cpp @@ -96,6 +96,63 @@ // printf("client Recv reply : %s\n", reply.data().c_str()); } +class TLMutex +{ + // typedef boost::interprocess::interprocess_mutex MutexT; + typedef CasMutex MutexT; + // typedef std::mutex MutexT; + typedef std::chrono::steady_clock Clock; + typedef Clock::duration Duration; + static Duration Now() { return Clock::now().time_since_epoch(); } + + const Duration limit_; + std::atomic<Duration> last_lock_time_; + MutexT mutex_; + +public: + struct Status { + int64_t nlock_ = 0; + int64_t nupdate_time_fail = 0; + int64_t nfail = 0; + int64_t nexcept = 0; + }; + Status st_; + + explicit TLMutex(Duration limit) : + limit_(limit) {} + TLMutex() : + TLMutex(std::chrono::seconds(1)) {} + ~TLMutex() { static_assert(std::is_pod<Duration>::value); } + bool try_lock() + { + if (mutex_.try_lock()) { + auto old_time = last_lock_time_.load(); + if (Now() - old_time > limit_) { + return last_lock_time_.compare_exchange_strong(old_time, Now()); + } else { + last_lock_time_.store(Now()); + return true; + } + } else { + auto old_time = last_lock_time_.load(); + if (Now() - old_time > limit_) { + return last_lock_time_.compare_exchange_strong(old_time, Now()); + } else { + return false; + } + } + } + void lock() + { + int n = 0; + while (!try_lock()) { + n++; + std::this_thread::yield(); + } + st_.nlock_ += n; + } + void unlock() { mutex_.unlock(); } +}; BOOST_AUTO_TEST_CASE(MutexTest) { const std::string shm_name("ShmMutex"); @@ -104,12 +161,42 @@ const std::string mtx_name("test_mutex"); const std::string int_name("test_int"); - auto mtx = shm.find_or_construct<Mutex>(mtx_name.c_str())(); + auto mtx = shm.find_or_construct<Mutex>(mtx_name.c_str())(3s); + auto pi = shm.find_or_construct<int>(int_name.c_str())(100); + typedef std::chrono::steady_clock Clock; + auto Now = []() { return Clock::now().time_since_epoch(); }; if (pi) { auto old = *pi; printf("int : %d, add1: %d\n", old, ++*pi); } + + { + boost::timer::auto_cpu_timer timer; + printf("test time: "); + TLMutex mutex; + // CasMutex mutex; + auto Lock = [&]() { + for (int i = 0; i < 1000 * 100; ++i) { + mutex.lock(); + mutex.unlock(); + } + }; + std::thread t1(Lock), t2(Lock); + t1.join(); + t2.join(); + printf("mutex nlock: %ld, update time error: %ld, normal fail: %ld, error wait: %ld\n", + mutex.st_.nlock_, + mutex.st_.nupdate_time_fail, + mutex.st_.nfail, + mutex.st_.nexcept); + } + + auto MSFromNow = [](const int ms) { + using namespace boost::posix_time; + ptime cur = boost::posix_time::microsec_clock::universal_time(); + return cur + millisec(ms); + }; auto TryLock = [&]() { if (mtx->try_lock()) { @@ -128,10 +215,17 @@ if (mtx) { printf("mtx exists\n"); if (TryLock()) { - if (TryLock()) { - Unlock(); - } + auto op = [&]() { + if (TryLock()) { + Unlock(); + } + }; + op(); + std::thread t(op); + t.join(); // Unlock(); + } else { + // mtx->unlock(); } } else { printf("mtx not exists\n"); -- Gitblit v1.8.0