mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
def ipc::uint<N>; optimize code
This commit is contained in:
parent
caabc24b71
commit
d5b5b3e0f4
@ -10,35 +10,62 @@
|
|||||||
namespace ipc {
|
namespace ipc {
|
||||||
namespace circ {
|
namespace circ {
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
struct alignas(std::max_align_t) elem_array_head {
|
struct alignas(std::max_align_t) elem_array_head {
|
||||||
using ui_t = std::uint8_t;
|
using u1_t = uint_t<N>;
|
||||||
using uc_t = std::uint16_t;
|
using u2_t = uint_t<N * 2>;
|
||||||
using ac_t = std::atomic<uc_t>;
|
|
||||||
|
|
||||||
std::atomic<std::size_t> lc_ { 0 }; // write spin lock flag
|
std::atomic<u2_t> cc_ { 0 }; // connection counter, using for broadcast
|
||||||
|
std::atomic<u2_t> wt_ { 0 }; // write index
|
||||||
|
std::atomic<u2_t> lc_ { 0 }; // write spin lock flag
|
||||||
|
|
||||||
ac_t cc_ { 0 }; // connection counter, using for broadcast
|
static u1_t index_of(u2_t c) { return static_cast<u1_t>(c); }
|
||||||
ac_t wt_ { 0 }; // write index
|
|
||||||
|
std::size_t connect(void) {
|
||||||
|
return cc_.fetch_add(1, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t disconnect(void) {
|
||||||
|
return cc_.fetch_sub(1, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t conn_count(void) const {
|
||||||
|
return cc_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto acquire(void) {
|
||||||
|
while (lc_.exchange(1, std::memory_order_acquire)) {
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
return index_of(wt_.load(std::memory_order_relaxed));
|
||||||
|
}
|
||||||
|
|
||||||
|
void commit(void) {
|
||||||
|
wt_.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
lc_.store(0, std::memory_order_release);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : std::size_t {
|
template <std::size_t N>
|
||||||
elem_array_head_size =
|
constexpr std::size_t elem_array_head_size =
|
||||||
(sizeof(elem_array_head) % alignof(std::max_align_t)) ?
|
(sizeof(elem_array_head<N>) % alignof(std::max_align_t)) ?
|
||||||
((sizeof(elem_array_head) / alignof(std::max_align_t)) + 1) * alignof(std::max_align_t) :
|
((sizeof(elem_array_head<N>) / alignof(std::max_align_t)) + 1) * alignof(std::max_align_t) :
|
||||||
sizeof(elem_array_head)
|
sizeof(elem_array_head<N>);
|
||||||
|
|
||||||
|
struct elem_head {
|
||||||
|
std::atomic<uint_t<32>> rc_ { 0 }; // read counter
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t DataSize>
|
template <std::size_t DataSize, std::size_t BaseIntSize = 8>
|
||||||
class elem_array : private elem_array_head {
|
class elem_array : private elem_array_head<BaseIntSize> {
|
||||||
struct head_t {
|
|
||||||
std::atomic<std::uint32_t> rc_ { 0 }; // read counter
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using base_t = elem_array_head<BaseIntSize>;
|
||||||
|
using head_t = elem_head;
|
||||||
|
|
||||||
enum : std::size_t {
|
enum : std::size_t {
|
||||||
head_size = elem_array_head_size,
|
head_size = elem_array_head_size<BaseIntSize>,
|
||||||
data_size = DataSize,
|
data_size = DataSize,
|
||||||
elem_max = std::numeric_limits<ui_t>::max() + 1, // default is 255 + 1
|
elem_max = std::numeric_limits<u1_t>::max() + 1, // default is 255 + 1
|
||||||
elem_size = sizeof(head_t) + DataSize,
|
elem_size = sizeof(head_t) + DataSize,
|
||||||
block_size = elem_size * elem_max
|
block_size = elem_size * elem_max
|
||||||
};
|
};
|
||||||
@ -54,21 +81,8 @@ private:
|
|||||||
return block_;
|
return block_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static elem_t* elem(void* ptr) {
|
static elem_t* elem(void* ptr) { return reinterpret_cast<elem_t*>(static_cast<byte_t*>(ptr) - sizeof(head_t)); }
|
||||||
return reinterpret_cast<elem_t*>(static_cast<byte_t*>(ptr) - sizeof(head_t));
|
elem_t* elem(u1_t i ) { return elem_start() + i; }
|
||||||
}
|
|
||||||
|
|
||||||
elem_t* elem(ui_t i) {
|
|
||||||
return elem_start() + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ui_t index_of(uc_t c) {
|
|
||||||
return static_cast<ui_t>(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_t index_of(elem_t* el) {
|
|
||||||
return static_cast<ui_t>(el - elem_start());
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
elem_array(void) = default;
|
elem_array(void) = default;
|
||||||
@ -78,48 +92,35 @@ public:
|
|||||||
elem_array(elem_array&&) = delete;
|
elem_array(elem_array&&) = delete;
|
||||||
elem_array& operator=(elem_array&&) = delete;
|
elem_array& operator=(elem_array&&) = delete;
|
||||||
|
|
||||||
std::size_t connect(void) {
|
using base_t::connect;
|
||||||
return cc_.fetch_add(1, std::memory_order_release);
|
using base_t::disconnect;
|
||||||
}
|
using base_t::conn_count;
|
||||||
|
|
||||||
std::size_t disconnect(void) {
|
|
||||||
return cc_.fetch_sub(1, std::memory_order_release);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t conn_count(void) const {
|
|
||||||
return cc_.load(std::memory_order_consume);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* acquire(void) {
|
void* acquire(void) {
|
||||||
while (lc_.exchange(1, std::memory_order_acquire)) {
|
elem_t* el = elem(base_t::acquire());
|
||||||
std::this_thread::yield();
|
|
||||||
}
|
|
||||||
elem_t* el = elem(index_of(wt_.load(std::memory_order_relaxed)));
|
|
||||||
// check all consumers have finished reading
|
// check all consumers have finished reading
|
||||||
while(1) {
|
while(1) {
|
||||||
std::uint32_t expected = 0;
|
uint_t<32> expected = 0;
|
||||||
if (el->head_.rc_.compare_exchange_weak(
|
if (el->head_.rc_.compare_exchange_weak(
|
||||||
expected,
|
expected,
|
||||||
static_cast<std::uint32_t>(cc_.load(std::memory_order_relaxed)),
|
static_cast<uint_t<32>>(conn_count()),
|
||||||
std::memory_order_release)) {
|
std::memory_order_release)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
|
||||||
}
|
}
|
||||||
return el->data_;
|
return el->data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void commit(void* /*ptr*/) {
|
void commit(void* /*ptr*/) {
|
||||||
wt_.fetch_add(1, std::memory_order_relaxed);
|
base_t::commit();
|
||||||
lc_.store(0, std::memory_order_release);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uc_t cursor(void) const {
|
u2_t cursor(void) const {
|
||||||
return wt_.load(std::memory_order_consume);
|
return wt_.load(std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* take(uc_t cursor) {
|
void* take(u2_t cursor) {
|
||||||
return elem(index_of(cursor))->data_;
|
return elem(index_of(cursor))->data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,16 @@ namespace ipc {
|
|||||||
|
|
||||||
using byte_t = std::uint8_t;
|
using byte_t = std::uint8_t;
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
struct uint;
|
||||||
|
|
||||||
|
template <> struct uint<8 > { using type = std::uint8_t ; };
|
||||||
|
template <> struct uint<16> { using type = std::uint16_t; };
|
||||||
|
template <> struct uint<32> { using type = std::uint32_t; };
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
using uint_t = typename uint<N>::type;
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
|
|
||||||
enum : std::size_t {
|
enum : std::size_t {
|
||||||
|
|||||||
@ -39,6 +39,8 @@ private slots:
|
|||||||
using cq_t = ipc::circ::elem_array<12>;
|
using cq_t = ipc::circ::elem_array<12>;
|
||||||
cq_t* cq__;
|
cq_t* cq__;
|
||||||
|
|
||||||
|
constexpr int LoopCount = 1000000;
|
||||||
|
|
||||||
void Unit::initTestCase(void) {
|
void Unit::initTestCase(void) {
|
||||||
TestSuite::initTestCase();
|
TestSuite::initTestCase();
|
||||||
cq__ = new cq_t;
|
cq__ = new cq_t;
|
||||||
@ -233,7 +235,7 @@ struct test_cq<ipc::circ::queue<T>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int N, int M, bool V = true, int Loops = 1000000, typename T>
|
template <int N, int M, bool V = true, int Loops = LoopCount, typename T>
|
||||||
void test_prod_cons(T* cq) {
|
void test_prod_cons(T* cq) {
|
||||||
test_cq<T> tcq { cq };
|
test_cq<T> tcq { cq };
|
||||||
|
|
||||||
@ -281,7 +283,7 @@ void test_prod_cons(T* cq) {
|
|||||||
for (auto& t : consumers) t.join();
|
for (auto& t : consumers) t.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int N, int M, bool V = true, int Loops = 1000000>
|
template <int N, int M, bool V = true, int Loops = LoopCount>
|
||||||
void test_prod_cons(void) {
|
void test_prod_cons(void) {
|
||||||
test_prod_cons<N, M, V, Loops>(cq__);
|
test_prod_cons<N, M, V, Loops>(cq__);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user