fix bug, remove rw_cas_lock

This commit is contained in:
mutouyun 2018-12-14 00:00:45 +08:00
parent 96c2a037f3
commit c47175360c
2 changed files with 23 additions and 58 deletions

View File

@ -8,46 +8,6 @@
namespace ipc { namespace ipc {
class rw_cas_lock {
std::atomic_size_t lc_ { 0 };
enum : std::size_t {
w_flag = (std::numeric_limits<std::size_t>::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 { class rw_lock {
using lc_ui_t = std::size_t; using lc_ui_t = std::size_t;
std::atomic<lc_ui_t> lc_ { 0 }; std::atomic<lc_ui_t> lc_ { 0 };
@ -59,26 +19,26 @@ class rw_lock {
public: public:
void lock() { void lock() {
auto old = lc_.fetch_or(w_flag, std::memory_order_acquire); for (unsigned k = 0;; ++k) {
if (!old) return; auto old = lc_.fetch_or(w_flag, std::memory_order_acquire);
// just like a spin-lock if (!old) return; // got w-lock
if (old & w_flag) for (unsigned k = 1; lc_.fetch_or(w_flag, std::memory_order_acquire) & w_flag; ++k) { if (!(old & w_flag)) break; // other thread having r-lock
yield(k); yield(k); // other thread having w-lock
} }
// wait for reading finished // 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); yield(k);
} }
} }
void unlock() { void unlock() {
lc_.fetch_and(w_mask, std::memory_order_release); lc_.store(0, std::memory_order_release);
} }
void lock_shared() { void lock_shared() {
for (unsigned k = 0;; ++k) { for (unsigned k = 0;; ++k) {
auto old = lc_.load(std::memory_order_relaxed); 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) && if (!(old & w_flag) &&
lc_.compare_exchange_weak(old, old + 1, std::memory_order_acquire)) { lc_.compare_exchange_weak(old, old + 1, std::memory_order_acquire)) {
break; break;

View File

@ -44,11 +44,12 @@ struct lc_wrapper : Mutex {
void unlock_shared() { Mutex::unlock(); } void unlock_shared() { Mutex::unlock(); }
}; };
template <typename Lc, int W = 4, int R = 4, int Loops = 100000> template <typename Lc, int W, int R, int Loops = 1000000>
void benchmark() { void benchmark() {
std::thread w_trd[W]; std::thread w_trd[W];
std::thread r_trd[R]; std::thread r_trd[R];
std::atomic_int fini { 0 }; std::atomic_int fini { 0 };
// std::atomic_bool wf { false };
std::vector<int> datas; std::vector<int> datas;
Lc lc; Lc lc;
@ -74,9 +75,11 @@ void benchmark() {
int x = -1; int x = -1;
{ {
std::shared_lock<Lc> guard { lc }; std::shared_lock<Lc> guard { lc };
// QVERIFY(!wf);
if (cnt < datas.size()) { if (cnt < datas.size()) {
x = datas[cnt]; x = datas[cnt];
} }
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
if (x == 0) break; // quit if (x == 0) break; // quit
if (x != -1) { if (x != -1) {
@ -100,8 +103,10 @@ void benchmark() {
for (int i = 1; i <= Loops; ++i) { for (int i = 1; i <= Loops; ++i) {
{ {
std::unique_lock<Lc> guard { lc }; std::unique_lock<Lc> guard { lc };
// wf = true;
datas.push_back(i); 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(); std::this_thread::yield();
} }
@ -123,17 +128,17 @@ void test_performance() {
<< std::endl; << std::endl;
benchmark<ipc::rw_lock , W, R>(); benchmark<ipc::rw_lock , W, R>();
// benchmark<ipc::rw_cas_lock , W, R>(); benchmark<ipc::rw_cas_lock , W, R>();
// benchmark<lc_wrapper<capo::spin_lock>, W, R>(); benchmark<lc_wrapper<capo::spin_lock>, W, R>();
// benchmark<lc_wrapper<std::mutex> , W, R>(); benchmark<lc_wrapper<std::mutex> , W, R>();
// benchmark<std::shared_timed_mutex , W, R>(); benchmark<std::shared_timed_mutex , W, R>();
} }
void Unit::test_rw_lock() { void Unit::test_rw_lock() {
test_performance<2, 1>(); test_performance<1, 1>();
// test_performance<4, 4>(); test_performance<4, 4>();
// test_performance<1, 8>(); test_performance<1, 8>();
// test_performance<8, 1>(); test_performance<8, 1>();
} }
void Unit::test_send_recv() { void Unit::test_send_recv() {