Complete the implementation of the clean interface and add unit tests

This commit is contained in:
mutouyun 2024-12-01 19:06:50 +08:00
parent 28fdf17279
commit 5e5b347636
7 changed files with 103 additions and 23 deletions

View File

@ -19,7 +19,7 @@ enum : unsigned {
template <typename Flag>
struct IPC_EXPORT chan_impl {
static ipc::handle_t inited();
static ipc::handle_t init_first();
static bool connect (ipc::handle_t * ph, char const * name, unsigned mode);
static bool connect (ipc::handle_t * ph, prefix, char const * name, unsigned mode);
@ -29,6 +29,9 @@ struct IPC_EXPORT chan_impl {
static char const * name(ipc::handle_t h);
// Release memory without waiting for the connection to disconnect.
static void release(ipc::handle_t h) noexcept;
// Force cleanup of all shared memory storage that handles depend on.
static void clear(ipc::handle_t h) noexcept;
static void clear_storage(char const * name) noexcept;
@ -49,7 +52,7 @@ class chan_wrapper {
private:
using detail_t = chan_impl<Flag>;
ipc::handle_t h_ = detail_t::inited();
ipc::handle_t h_ = detail_t::init_first();
unsigned mode_ = ipc::sender;
bool connected_ = false;
@ -88,15 +91,24 @@ public:
return detail_t::name(h_);
}
// Release memory without waiting for the connection to disconnect.
void release() noexcept {
detail_t::release(h_);
h_ = nullptr;
}
// Clear shared memory files under opened handle.
void clear() noexcept {
detail_t::clear(h_);
h_ = nullptr;
}
// Clear shared memory files under a specific name.
static void clear_storage(char const * name) noexcept {
detail_t::clear_storage(name);
}
// Clear shared memory files under a specific name with a prefix.
static void clear_storage(prefix pref, char const * name) noexcept {
detail_t::clear_storage(pref, name);
}

View File

@ -395,10 +395,10 @@ struct queue_generator {
conn_info_head::init();
if (!que_.valid()) {
que_.open(ipc::make_prefix(prefix_, {
"QU_CONN__",
ipc::to_string(DataSize), "__",
ipc::to_string(AlignSize), "__",
this->name_}).c_str());
"QU_CONN__",
this->name_,
"__", ipc::to_string(DataSize),
"__", ipc::to_string(AlignSize)}).c_str());
}
}
@ -408,11 +408,11 @@ struct queue_generator {
}
static void clear_storage(char const * prefix, char const * name) noexcept {
queue_t::clear_storage(ipc::make_prefix(prefix, {
"QU_CONN__",
ipc::to_string(DataSize), "__",
ipc::to_string(AlignSize), "__",
name}).c_str());
queue_t::clear_storage(ipc::make_prefix(ipc::make_string(prefix), {
"QU_CONN__",
ipc::make_string(name),
"__", ipc::to_string(DataSize),
"__", ipc::to_string(AlignSize)}).c_str());
conn_info_head::clear_storage(prefix, name);
}
@ -489,8 +489,7 @@ static bool reconnect(ipc::handle_t * ph, bool start_to_recv) {
return que->ready_sending();
}
static void destroy(ipc::handle_t h) {
disconnect(h);
static void destroy(ipc::handle_t h) noexcept {
ipc::mem::free(info_of(h));
}
@ -733,7 +732,7 @@ using policy_t = ipc::policy::choose<ipc::circ::elem_array, Flag>;
namespace ipc {
template <typename Flag>
ipc::handle_t chan_impl<Flag>::inited() {
ipc::handle_t chan_impl<Flag>::init_first() {
ipc::detail::waiter::init();
return nullptr;
}
@ -760,6 +759,12 @@ void chan_impl<Flag>::disconnect(ipc::handle_t h) {
template <typename Flag>
void chan_impl<Flag>::destroy(ipc::handle_t h) {
disconnect(h);
detail_impl<policy_t<Flag>>::destroy(h);
}
template <typename Flag>
void chan_impl<Flag>::release(ipc::handle_t h) noexcept {
detail_impl<policy_t<Flag>>::destroy(h);
}

View File

@ -195,9 +195,11 @@ public:
void clear() noexcept {
if (mutex_ != nullptr) {
if (mutex_->name() != nullptr) {
release_mutex(mutex_->name(), [] { return true; });
}
mutex_->clear();
release_mutex(mutex_->name(), [this] {
mutex_->clear();
return true;
});
} else mutex_->clear();
}
mutex_ = nullptr;
ref_ = nullptr;

View File

@ -177,10 +177,10 @@ public:
if ((eno = ::pthread_mutex_destroy(mutex_)) != 0) {
ipc::error("fail pthread_mutex_destroy[%d]\n", eno);
}
shm_->clear();
return true;
});
}
shm_->clear();
} else shm_->clear();
}
shm_ = nullptr;
ref_ = nullptr;

View File

@ -151,6 +151,50 @@ void test_sr(char const * name, int s_cnt, int r_cnt) {
} // internal-linkage
TEST(IPC, clear) {
{
chan<relat::single, relat::single, trans::unicast> c{"ssu"};
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", true));
c.clear();
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", false));
}
{
chan<relat::single, relat::single, trans::unicast> c{"ssu"};
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", true));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", true));
chan<relat::single, relat::single, trans::unicast>::clear_storage("ssu");
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__AC_CONN__ssu", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__CC_CONN__ssu_WAITER_LOCK_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__RD_CONN__ssu_WAITER_LOCK_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__WT_CONN__ssu_WAITER_LOCK_", false));
EXPECT_TRUE(ipc_ut::expect_exist("__IPC_SHM__QU_CONN__ssu__64__16", false));
c.release(); // Call this interface to prevent destruction-time exceptions.
}
}
TEST(IPC, basic_ssu) {
test_basic<relat::single, relat::single, trans::unicast >("ssu");
}

View File

@ -205,4 +205,4 @@ TEST(Sync, ConditionRobust) {
ASSERT_TRUE(lock.unlock());
printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 6\n");
unlock.join();
}
}

View File

@ -4,8 +4,6 @@
#include "libipc/waiter.h"
#include "test.h"
namespace {
TEST(Waiter, broadcast) {
for (int i = 0; i < 10; ++i) {
ipc::detail::waiter waiter;
@ -65,4 +63,23 @@ TEST(Waiter, quit_waiting) {
std::cout << "quit... \n";
}
} // internal-linkage
TEST(Waiter, clear) {
{
ipc::detail::waiter w{"my-waiter"};
ASSERT_TRUE(w.valid());
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", true));
w.clear();
ASSERT_TRUE(!w.valid());
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", false));
}
{
ipc::detail::waiter w{"my-waiter"};
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", true));
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", true));
ipc::detail::waiter::clear_storage("my-waiter");
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_COND_", false));
EXPECT_TRUE(ipc_ut::expect_exist("my-waiter_WAITER_LOCK_", false));
}
}