From c4617a229030a49032ae5b7bc57639d35414218f Mon Sep 17 00:00:00 2001 From: mutouyun Date: Fri, 1 Jan 2021 13:28:25 +0800 Subject: [PATCH] 'elem-array::connect' should always return 0 when the connection-slot is full. --- src/ipc.cpp | 6 ++++++ src/libipc/circ/elem_def.h | 8 ++++++-- test/test_queue.cpp | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ipc.cpp b/src/ipc.cpp index 9bfa291..46c2859 100755 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -422,6 +422,12 @@ static bool send(F&& gen_push, ipc::handle_t h, void const * data, std::size_t s ipc::error("fail: send, queue_of(h)->elems() == nullptr\n"); return false; } + /** + * If the que hasn't connected as a receiver, the 'connected-id' must be 0, + * and 'connections' equals to 0 only if there are no receivers. + * Or if the que has connected as a receiver, + * 'connections' equals to 'connected-id' of this que only if there are no other receivers. + */ if (que->elems()->connections(std::memory_order_relaxed) == que->connected_id()) { // there is no receiver on this connection return false; diff --git a/src/libipc/circ/elem_def.h b/src/libipc/circ/elem_def.h index 4b9feb8..b608581 100755 --- a/src/libipc/circ/elem_def.h +++ b/src/libipc/circ/elem_def.h @@ -23,9 +23,9 @@ constexpr u1_t index_of(u2_t c) noexcept { } class conn_head { - std::atomic cc_; // connections + std::atomic cc_{0}; // connections ipc::spin_lock lc_; - std::atomic constructed_; + std::atomic constructed_{false}; public: void init() { @@ -47,6 +47,10 @@ public: for (unsigned k = 0;;) { cc_t curr = cc_.load(std::memory_order_acquire); cc_t next = curr | (curr + 1); // find the first 0, and set it to 1. + if (next == 0) { + // connection-slot is full. + return 0; + } if (cc_.compare_exchange_weak(curr, next, std::memory_order_release)) { return next ^ curr; // return connected id } diff --git a/test/test_queue.cpp b/test/test_queue.cpp index c10d3c9..68c190b 100755 --- a/test/test_queue.cpp +++ b/test/test_queue.cpp @@ -127,6 +127,20 @@ TEST(Queue, check_size) { std::cout << "sizeof(elems_t) = " << sizeof(el_t) << std::endl; } +TEST(Queue, connection) { + { + using el_t = elems_t; + el_t el; + el.init(); + for (std::size_t i = 0; i < (sizeof(ipc::circ::cc_t) * CHAR_BIT); ++i) { + EXPECT_NE(el.connect(), 0); + } + for (std::size_t i = 0; i < 10000; ++i) { + EXPECT_EQ(el.connect(), 0); + } + } +} + TEST(Queue, prod_cons_1v1_unicast) { test_sr(elems_t {}, 1, 1, "ssu"); test_sr(elems_t {}, 1, 1, "smu");