'elem-array::connect' should always return 0 when the connection-slot is full.

This commit is contained in:
mutouyun 2021-01-01 13:28:25 +08:00
parent af6ac84110
commit c4617a2290
3 changed files with 26 additions and 2 deletions

View File

@ -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"); ipc::error("fail: send, queue_of(h)->elems() == nullptr\n");
return false; 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()) { if (que->elems()->connections(std::memory_order_relaxed) == que->connected_id()) {
// there is no receiver on this connection // there is no receiver on this connection
return false; return false;

View File

@ -23,9 +23,9 @@ constexpr u1_t index_of(u2_t c) noexcept {
} }
class conn_head { class conn_head {
std::atomic<cc_t> cc_; // connections std::atomic<cc_t> cc_{0}; // connections
ipc::spin_lock lc_; ipc::spin_lock lc_;
std::atomic<bool> constructed_; std::atomic<bool> constructed_{false};
public: public:
void init() { void init() {
@ -47,6 +47,10 @@ public:
for (unsigned k = 0;;) { for (unsigned k = 0;;) {
cc_t curr = cc_.load(std::memory_order_acquire); cc_t curr = cc_.load(std::memory_order_acquire);
cc_t next = curr | (curr + 1); // find the first 0, and set it to 1. 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)) { if (cc_.compare_exchange_weak(curr, next, std::memory_order_release)) {
return next ^ curr; // return connected id return next ^ curr; // return connected id
} }

View File

@ -127,6 +127,20 @@ TEST(Queue, check_size) {
std::cout << "sizeof(elems_t<s, m, b>) = " << sizeof(el_t) << std::endl; std::cout << "sizeof(elems_t<s, m, b>) = " << sizeof(el_t) << std::endl;
} }
TEST(Queue, connection) {
{
using el_t = elems_t<ipc::relat::single, ipc::relat::multi, ipc::trans::broadcast>;
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(Queue, prod_cons_1v1_unicast) {
test_sr(elems_t<ipc::relat::single, ipc::relat::single, ipc::trans::unicast> {}, 1, 1, "ssu"); test_sr(elems_t<ipc::relat::single, ipc::relat::single, ipc::trans::unicast> {}, 1, 1, "ssu");
test_sr(elems_t<ipc::relat::single, ipc::relat::multi , ipc::trans::unicast> {}, 1, 1, "smu"); test_sr(elems_t<ipc::relat::single, ipc::relat::multi , ipc::trans::unicast> {}, 1, 1, "smu");