mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
Complete the implementation of the clean interface and add unit tests
This commit is contained in:
parent
28fdf17279
commit
5e5b347636
@ -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);
|
||||
}
|
||||
|
||||
@ -396,9 +396,9 @@ struct queue_generator {
|
||||
if (!que_.valid()) {
|
||||
que_.open(ipc::make_prefix(prefix_, {
|
||||
"QU_CONN__",
|
||||
ipc::to_string(DataSize), "__",
|
||||
ipc::to_string(AlignSize), "__",
|
||||
this->name_}).c_str());
|
||||
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, {
|
||||
queue_t::clear_storage(ipc::make_prefix(ipc::make_string(prefix), {
|
||||
"QU_CONN__",
|
||||
ipc::to_string(DataSize), "__",
|
||||
ipc::to_string(AlignSize), "__",
|
||||
name}).c_str());
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user