diff --git a/include/rw_lock.h b/include/rw_lock.h index 28bb99d..ddf95e2 100644 --- a/include/rw_lock.h +++ b/include/rw_lock.h @@ -8,46 +8,6 @@ namespace ipc { -class rw_cas_lock { - std::atomic_size_t lc_ { 0 }; - - enum : std::size_t { - w_flag = (std::numeric_limits::max)() - }; - -public: - void lock() { - for (unsigned k = 0;; ++k) { - std::size_t expected = 0; - if (lc_.compare_exchange_weak(expected, w_flag, std::memory_order_acquire)) { - break; - } - yield(k); - } - } - - void unlock() { - lc_.store(0, std::memory_order_release); - } - - void lock_shared() { - for (unsigned k = 0;; ++k) { - std::size_t old = lc_.load(std::memory_order_relaxed); - std::size_t unlocked = old + 1; - if (unlocked && - lc_.compare_exchange_weak(old, unlocked, std::memory_order_acquire)) { - break; - } - yield(k); - std::atomic_thread_fence(std::memory_order_acquire); - } - } - - void unlock_shared() { - lc_.fetch_sub(1, std::memory_order_release); - } -}; - class rw_lock { using lc_ui_t = std::size_t; std::atomic lc_ { 0 }; @@ -59,26 +19,26 @@ class rw_lock { public: void lock() { - auto old = lc_.fetch_or(w_flag, std::memory_order_acquire); - if (!old) return; - // just like a spin-lock - if (old & w_flag) for (unsigned k = 1; lc_.fetch_or(w_flag, std::memory_order_acquire) & w_flag; ++k) { - yield(k); + for (unsigned k = 0;; ++k) { + auto old = lc_.fetch_or(w_flag, std::memory_order_acquire); + if (!old) return; // got w-lock + if (!(old & w_flag)) break; // other thread having r-lock + yield(k); // other thread having w-lock } // wait for reading finished - else for (unsigned k = 1; lc_.load(std::memory_order_acquire) & w_mask; ++k) { + for (unsigned k = 0; lc_.load(std::memory_order_acquire) & w_mask; ++k) { yield(k); } } void unlock() { - lc_.fetch_and(w_mask, std::memory_order_release); + lc_.store(0, std::memory_order_release); } void lock_shared() { for (unsigned k = 0;; ++k) { auto old = lc_.load(std::memory_order_relaxed); - // if w_flag set, just continue; otherwise cas ++ + // if w_flag set, just continue; otherwise cas lc + 1 (set r-lock) if (!(old & w_flag) && lc_.compare_exchange_weak(old, old + 1, std::memory_order_acquire)) { break; diff --git a/test/test_ipc.cpp b/test/test_ipc.cpp index 01853e0..2738013 100644 --- a/test/test_ipc.cpp +++ b/test/test_ipc.cpp @@ -44,11 +44,12 @@ struct lc_wrapper : Mutex { void unlock_shared() { Mutex::unlock(); } }; -template +template void benchmark() { std::thread w_trd[W]; std::thread r_trd[R]; std::atomic_int fini { 0 }; +// std::atomic_bool wf { false }; std::vector datas; Lc lc; @@ -74,9 +75,11 @@ void benchmark() { int x = -1; { std::shared_lock guard { lc }; +// QVERIFY(!wf); if (cnt < datas.size()) { x = datas[cnt]; } +// std::this_thread::sleep_for(std::chrono::milliseconds(1)); } if (x == 0) break; // quit if (x != -1) { @@ -100,8 +103,10 @@ void benchmark() { for (int i = 1; i <= Loops; ++i) { { std::unique_lock guard { lc }; +// wf = true; datas.push_back(i); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); +// std::this_thread::sleep_for(std::chrono::milliseconds(1)); +// wf = false; } std::this_thread::yield(); } @@ -123,17 +128,17 @@ void test_performance() { << std::endl; benchmark(); -// benchmark(); -// benchmark, W, R>(); -// benchmark , W, R>(); -// benchmark(); + benchmark(); + benchmark, W, R>(); + benchmark , W, R>(); + benchmark(); } void Unit::test_rw_lock() { - test_performance<2, 1>(); -// test_performance<4, 4>(); -// test_performance<1, 8>(); -// test_performance<8, 1>(); + test_performance<1, 1>(); + test_performance<4, 4>(); + test_performance<1, 8>(); + test_performance<8, 1>(); } void Unit::test_send_recv() {