mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
use std::atomic<std::size_t> instead of flag for better performance in arm; cross-platform supporting; add more test cases
This commit is contained in:
parent
b3e2c80fc0
commit
c8e81e2794
@ -16,10 +16,10 @@ struct alignas(std::max_align_t) elem_array_head {
|
|||||||
using uc_t = std::uint16_t;
|
using uc_t = std::uint16_t;
|
||||||
using ac_t = std::atomic<uc_t>;
|
using ac_t = std::atomic<uc_t>;
|
||||||
|
|
||||||
|
std::atomic<std::size_t> lc_ { 0 }; // write spin lock flag
|
||||||
|
|
||||||
ac_t cc_ { 0 }; // connection counter, using for broadcast
|
ac_t cc_ { 0 }; // connection counter, using for broadcast
|
||||||
ac_t wt_ { 0 }; // write index
|
ac_t wt_ { 0 }; // write index
|
||||||
|
|
||||||
std::atomic_flag lc_ ATOMIC_FLAG_INIT; // write spin lock flag
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : std::size_t {
|
enum : std::size_t {
|
||||||
@ -93,7 +93,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* acquire(void) {
|
void* acquire(void) {
|
||||||
while (lc_.test_and_set(std::memory_order_acquire)) {
|
while (lc_.exchange(1, std::memory_order_acquire)) {
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
elem_t* el = elem(wt_.load(std::memory_order_relaxed));
|
elem_t* el = elem(wt_.load(std::memory_order_relaxed));
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
|
|
||||||
void commit(void* /*ptr*/) {
|
void commit(void* /*ptr*/) {
|
||||||
wt_.fetch_add(1, std::memory_order_relaxed);
|
wt_.fetch_add(1, std::memory_order_relaxed);
|
||||||
lc_.clear(std::memory_order_release);
|
lc_.store(0, std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
uc_t cursor(void) const {
|
uc_t cursor(void) const {
|
||||||
|
|||||||
@ -84,8 +84,27 @@ public:
|
|||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool push(T const & item) {
|
||||||
|
if (elems_ == nullptr) return false;
|
||||||
|
auto ptr = elems_->acquire();
|
||||||
|
::new (ptr) T(item);
|
||||||
|
elems_->commit(ptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P>
|
||||||
|
auto push(P&& param) // disable this if P is the same as T
|
||||||
|
-> std::enable_if_t<!std::is_same<std::remove_reference_t<P>, T>::value, bool> {
|
||||||
|
if (elems_ == nullptr) return false;
|
||||||
|
auto ptr = elems_->acquire();
|
||||||
|
::new (ptr) T { std::forward<P>(param) };
|
||||||
|
elems_->commit(ptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... P>
|
template <typename... P>
|
||||||
bool push(P&&... params) {
|
auto push(P&&... params) // some old compilers are not support this well
|
||||||
|
-> std::enable_if_t<(sizeof...(P) != 1), bool> {
|
||||||
if (elems_ == nullptr) return false;
|
if (elems_ == nullptr) return false;
|
||||||
auto ptr = elems_->acquire();
|
auto ptr = elems_->acquire();
|
||||||
::new (ptr) T { std::forward<P>(params)... };
|
::new (ptr) T { std::forward<P>(params)... };
|
||||||
|
|||||||
@ -293,41 +293,42 @@ void Unit::test_prod_cons_3v1(void) {
|
|||||||
test_prod_cons<3, 1>();
|
test_prod_cons<3, 1>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int B, int E>
|
template <int P, int C>
|
||||||
struct test_cons_performance {
|
struct test_performance {
|
||||||
static void start(void) {
|
static void start(void) {
|
||||||
test_prod_cons<1, B, false>();
|
test_performance<P - 1, C - 1>::start();
|
||||||
test_cons_performance<B + 1, E>::start();
|
test_prod_cons<P, C, false>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int E>
|
template <int C>
|
||||||
struct test_cons_performance<E, E> {
|
struct test_performance<1, C> {
|
||||||
static void start(void) {
|
static void start(void) {
|
||||||
test_prod_cons<1, E, false>();
|
test_performance<1, C - 1>::start();
|
||||||
|
test_prod_cons<1, C, false>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int B, int E>
|
template <int P>
|
||||||
struct test_prod_performance {
|
struct test_performance<P, 1> {
|
||||||
static void start(void) {
|
static void start(void) {
|
||||||
test_prod_cons<B, 1, false>();
|
test_performance<P - 1, 1>::start();
|
||||||
test_prod_performance<B + 1, E>::start();
|
test_prod_cons<P, 1, false>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int E>
|
template <>
|
||||||
struct test_prod_performance<E, E> {
|
struct test_performance<1, 1> {
|
||||||
static void start(void) {
|
static void start(void) {
|
||||||
test_prod_cons<E, 1, false>();
|
test_prod_cons<1, 1, false>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Unit::test_prod_cons_performance(void) {
|
void Unit::test_prod_cons_performance(void) {
|
||||||
test_cons_performance<1, 10>::start();
|
test_performance<1 , 10>::start();
|
||||||
test_prod_performance<1, 10>::start();
|
test_performance<10, 1 >::start();
|
||||||
test_prod_cons<3, 3, false>(); // just test
|
test_performance<10, 10>::start();
|
||||||
test_prod_cons<5, 5>(); // test & verify
|
test_prod_cons <3 , 3 >(); // test & verify
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::test_queue(void) {
|
void Unit::test_queue(void) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user