Skip to content

Commit 5e5b347

Browse files
committed
Complete the implementation of the clean interface and add unit tests
1 parent 28fdf17 commit 5e5b347

File tree

7 files changed

+103
-23
lines changed

7 files changed

+103
-23
lines changed

include/libipc/ipc.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ enum : unsigned {
1919

2020
template <typename Flag>
2121
struct IPC_EXPORT chan_impl {
22-
static ipc::handle_t inited();
22+
static ipc::handle_t init_first();
2323

2424
static bool connect (ipc::handle_t * ph, char const * name, unsigned mode);
2525
static bool connect (ipc::handle_t * ph, prefix, char const * name, unsigned mode);
@@ -29,6 +29,9 @@ struct IPC_EXPORT chan_impl {
2929

3030
static char const * name(ipc::handle_t h);
3131

32+
// Release memory without waiting for the connection to disconnect.
33+
static void release(ipc::handle_t h) noexcept;
34+
3235
// Force cleanup of all shared memory storage that handles depend on.
3336
static void clear(ipc::handle_t h) noexcept;
3437
static void clear_storage(char const * name) noexcept;
@@ -49,7 +52,7 @@ class chan_wrapper {
4952
private:
5053
using detail_t = chan_impl<Flag>;
5154

52-
ipc::handle_t h_ = detail_t::inited();
55+
ipc::handle_t h_ = detail_t::init_first();
5356
unsigned mode_ = ipc::sender;
5457
bool connected_ = false;
5558

@@ -88,15 +91,24 @@ class chan_wrapper {
8891
return detail_t::name(h_);
8992
}
9093

94+
// Release memory without waiting for the connection to disconnect.
95+
void release() noexcept {
96+
detail_t::release(h_);
97+
h_ = nullptr;
98+
}
99+
91100
// Clear shared memory files under opened handle.
92101
void clear() noexcept {
93102
detail_t::clear(h_);
103+
h_ = nullptr;
94104
}
95105

106+
// Clear shared memory files under a specific name.
96107
static void clear_storage(char const * name) noexcept {
97108
detail_t::clear_storage(name);
98109
}
99110

111+
// Clear shared memory files under a specific name with a prefix.
100112
static void clear_storage(prefix pref, char const * name) noexcept {
101113
detail_t::clear_storage(pref, name);
102114
}

src/libipc/ipc.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,10 @@ struct queue_generator {
395395
conn_info_head::init();
396396
if (!que_.valid()) {
397397
que_.open(ipc::make_prefix(prefix_, {
398-
"QU_CONN__",
399-
ipc::to_string(DataSize), "__",
400-
ipc::to_string(AlignSize), "__",
401-
this->name_}).c_str());
398+
"QU_CONN__",
399+
this->name_,
400+
"__", ipc::to_string(DataSize),
401+
"__", ipc::to_string(AlignSize)}).c_str());
402402
}
403403
}
404404

@@ -408,11 +408,11 @@ struct queue_generator {
408408
}
409409

410410
static void clear_storage(char const * prefix, char const * name) noexcept {
411-
queue_t::clear_storage(ipc::make_prefix(prefix, {
412-
"QU_CONN__",
413-
ipc::to_string(DataSize), "__",
414-
ipc::to_string(AlignSize), "__",
415-
name}).c_str());
411+
queue_t::clear_storage(ipc::make_prefix(ipc::make_string(prefix), {
412+
"QU_CONN__",
413+
ipc::make_string(name),
414+
"__", ipc::to_string(DataSize),
415+
"__", ipc::to_string(AlignSize)}).c_str());
416416
conn_info_head::clear_storage(prefix, name);
417417
}
418418

@@ -489,8 +489,7 @@ static bool reconnect(ipc::handle_t * ph, bool start_to_recv) {
489489
return que->ready_sending();
490490
}
491491

492-
static void destroy(ipc::handle_t h) {
493-
disconnect(h);
492+
static void destroy(ipc::handle_t h) noexcept {
494493
ipc::mem::free(info_of(h));
495494
}
496495

@@ -733,7 +732,7 @@ using policy_t = ipc::policy::choose<ipc::circ::elem_array, Flag>;
733732
namespace ipc {
734733

735734
template <typename Flag>
736-
ipc::handle_t chan_impl<Flag>::inited() {
735+
ipc::handle_t chan_impl<Flag>::init_first() {
737736
ipc::detail::waiter::init();
738737
return nullptr;
739738
}
@@ -760,6 +759,12 @@ void chan_impl<Flag>::disconnect(ipc::handle_t h) {
760759

761760
template <typename Flag>
762761
void chan_impl<Flag>::destroy(ipc::handle_t h) {
762+
disconnect(h);
763+
detail_impl<policy_t<Flag>>::destroy(h);
764+
}
765+
766+
template <typename Flag>
767+
void chan_impl<Flag>::release(ipc::handle_t h) noexcept {
763768
detail_impl<policy_t<Flag>>::destroy(h);
764769
}
765770

src/libipc/platform/linux/mutex.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,11 @@ class mutex {
195195
void clear() noexcept {
196196
if (mutex_ != nullptr) {
197197
if (mutex_->name() != nullptr) {
198-
release_mutex(mutex_->name(), [] { return true; });
199-
}
200-
mutex_->clear();
198+
release_mutex(mutex_->name(), [this] {
199+
mutex_->clear();
200+
return true;
201+
});
202+
} else mutex_->clear();
201203
}
202204
mutex_ = nullptr;
203205
ref_ = nullptr;

src/libipc/platform/posix/mutex.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,10 @@ class mutex {
177177
if ((eno = ::pthread_mutex_destroy(mutex_)) != 0) {
178178
ipc::error("fail pthread_mutex_destroy[%d]\n", eno);
179179
}
180+
shm_->clear();
180181
return true;
181182
});
182-
}
183-
shm_->clear();
183+
} else shm_->clear();
184184
}
185185
shm_ = nullptr;
186186
ref_ = nullptr;

test/test_ipc.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,50 @@ void test_sr(char const * name, int s_cnt, int r_cnt) {
151151

152152
} // internal-linkage
153153

154+
TEST(IPC, clear) {
155+
{
156+
chan<relat::single, relat::single, trans::unicast> c{"ssu"};
157+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", true));
158+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", true));
159+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", true));
160+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", true));
161+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", true));
162+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", true));
163+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", true));
164+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", true));
165+
c.clear();
166+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", false));
167+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", false));
168+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", false));
169+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", false));
170+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", false));
171+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", false));
172+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", false));
173+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", false));
174+
}
175+
{
176+
chan<relat::single, relat::single, trans::unicast> c{"ssu"};
177+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", true));
178+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", true));
179+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", true));
180+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", true));
181+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", true));
182+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", true));
183+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", true));
184+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", true));
185+
chan<relat::single, relat::single, trans::unicast>::clear_storage("ssu");
186+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", false));
187+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", false));
188+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", false));
189+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", false));
190+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", false));
191+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", false));
192+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", false));
193+
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", false));
194+
c.release(); // Call this interface to prevent destruction-time exceptions.
195+
}
196+
}
197+
154198
TEST(IPC, basic_ssu) {
155199
test_basic<relat::single, relat::single, trans::unicast >("ssu");
156200
}

test/test_sync.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,4 @@ TEST(Sync, ConditionRobust) {
205205
ASSERT_TRUE(lock.unlock());
206206
printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 6\n");
207207
unlock.join();
208-
}
208+
}

test/test_waiter.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#include "libipc/waiter.h"
55
#include "test.h"
66

7-
namespace {
8-
97
TEST(Waiter, broadcast) {
108
for (int i = 0; i < 10; ++i) {
119
ipc::detail::waiter waiter;
@@ -65,4 +63,23 @@ TEST(Waiter, quit_waiting) {
6563
std::cout << "quit... \n";
6664
}
6765

68-
} // internal-linkage
66+
TEST(Waiter, clear) {
67+
{
68+
ipc::detail::waiter w{"my-waiter"};
69+
ASSERT_TRUE(w.valid());
70+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", true));
71+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", true));
72+
w.clear();
73+
ASSERT_TRUE(!w.valid());
74+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", false));
75+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", false));
76+
}
77+
{
78+
ipc::detail::waiter w{"my-waiter"};
79+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", true));
80+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", true));
81+
ipc::detail::waiter::clear_storage("my-waiter");
82+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", false));
83+
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", false));
84+
}
85+
}

0 commit comments

Comments
 (0)