mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
considering a different implementation, may have bugs
This commit is contained in:
parent
a26f171124
commit
96c2a037f3
@ -17,6 +17,7 @@ struct uint;
|
|||||||
template <> struct uint<8 > { using type = std::uint8_t ; };
|
template <> struct uint<8 > { using type = std::uint8_t ; };
|
||||||
template <> struct uint<16> { using type = std::uint16_t; };
|
template <> struct uint<16> { using type = std::uint16_t; };
|
||||||
template <> struct uint<32> { using type = std::uint32_t; };
|
template <> struct uint<32> { using type = std::uint32_t; };
|
||||||
|
template <> struct uint<64> { using type = std::uint64_t; };
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
using uint_t = typename uint<N>::type;
|
using uint_t = typename uint<N>::type;
|
||||||
|
|||||||
@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
class rw_lock {
|
class rw_cas_lock {
|
||||||
std::atomic_size_t lc_ { 0 };
|
std::atomic_size_t lc_ { 0 };
|
||||||
|
|
||||||
enum : std::size_t {
|
enum : std::size_t {
|
||||||
@ -18,7 +19,7 @@ public:
|
|||||||
void lock() {
|
void lock() {
|
||||||
for (unsigned k = 0;; ++k) {
|
for (unsigned k = 0;; ++k) {
|
||||||
std::size_t expected = 0;
|
std::size_t expected = 0;
|
||||||
if (lc_.compare_exchange_weak(expected, w_flag, std::memory_order_acq_rel)) {
|
if (lc_.compare_exchange_weak(expected, w_flag, std::memory_order_acquire)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yield(k);
|
yield(k);
|
||||||
@ -34,7 +35,52 @@ public:
|
|||||||
std::size_t old = lc_.load(std::memory_order_relaxed);
|
std::size_t old = lc_.load(std::memory_order_relaxed);
|
||||||
std::size_t unlocked = old + 1;
|
std::size_t unlocked = old + 1;
|
||||||
if (unlocked &&
|
if (unlocked &&
|
||||||
lc_.compare_exchange_weak(old, unlocked, std::memory_order_acq_rel)) {
|
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_ui_t> lc_ { 0 };
|
||||||
|
|
||||||
|
enum : lc_ui_t {
|
||||||
|
w_mask = (std::numeric_limits<std::make_signed_t<lc_ui_t>>::max)(), // b 0111 1111
|
||||||
|
w_flag = w_mask + 1 // b 1000 0000
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// wait for reading finished
|
||||||
|
else for (unsigned k = 1; lc_.load(std::memory_order_acquire) & w_mask; ++k) {
|
||||||
|
yield(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock() {
|
||||||
|
lc_.fetch_and(w_mask, 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 (!(old & w_flag) &&
|
||||||
|
lc_.compare_exchange_weak(old, old + 1, std::memory_order_acquire)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yield(k);
|
yield(k);
|
||||||
|
|||||||
@ -31,7 +31,7 @@ private slots:
|
|||||||
void test_prod_cons_performance();
|
void test_prod_cons_performance();
|
||||||
|
|
||||||
void test_queue();
|
void test_queue();
|
||||||
} unit__;
|
} /*unit__*/;
|
||||||
|
|
||||||
#include "test_circ.moc"
|
#include "test_circ.moc"
|
||||||
|
|
||||||
|
|||||||
@ -101,6 +101,7 @@ void benchmark() {
|
|||||||
{
|
{
|
||||||
std::unique_lock<Lc> guard { lc };
|
std::unique_lock<Lc> guard { lc };
|
||||||
datas.push_back(i);
|
datas.push_back(i);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
@ -122,16 +123,17 @@ void test_performance() {
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
benchmark<ipc::rw_lock , W, R>();
|
benchmark<ipc::rw_lock , W, R>();
|
||||||
benchmark<lc_wrapper<capo::spin_lock>, W, R>();
|
// benchmark<ipc::rw_cas_lock , W, R>();
|
||||||
benchmark<lc_wrapper<std::mutex> , W, R>();
|
// benchmark<lc_wrapper<capo::spin_lock>, W, R>();
|
||||||
benchmark<std::shared_timed_mutex , W, R>();
|
// benchmark<lc_wrapper<std::mutex> , W, R>();
|
||||||
|
// benchmark<std::shared_timed_mutex , W, R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::test_rw_lock() {
|
void Unit::test_rw_lock() {
|
||||||
test_performance<1, 1>();
|
test_performance<2, 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() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user