diff --git a/include/libipc/condition.h b/include/libipc/condition.h index a4e2ac3..072074a 100644 --- a/include/libipc/condition.h +++ b/include/libipc/condition.h @@ -26,6 +26,9 @@ public: bool open(char const *name) noexcept; void close() noexcept; + void clear() noexcept; + static void clear_storage(char const * name) noexcept; + bool wait(ipc::sync::mutex &mtx, std::uint64_t tm = ipc::invalid_value) noexcept; bool notify(ipc::sync::mutex &mtx) noexcept; bool broadcast(ipc::sync::mutex &mtx) noexcept; diff --git a/include/libipc/mutex.h b/include/libipc/mutex.h index 2d4781f..0b2a0e4 100644 --- a/include/libipc/mutex.h +++ b/include/libipc/mutex.h @@ -26,6 +26,9 @@ public: bool open(char const *name) noexcept; void close() noexcept; + void clear() noexcept; + static void clear_storage(char const * name) noexcept; + bool lock(std::uint64_t tm = ipc::invalid_value) noexcept; bool try_lock() noexcept(false); // std::system_error bool unlock() noexcept; diff --git a/include/libipc/semaphore.h b/include/libipc/semaphore.h index 7f557e2..397ec3e 100644 --- a/include/libipc/semaphore.h +++ b/include/libipc/semaphore.h @@ -25,6 +25,9 @@ public: bool open(char const *name, std::uint32_t count = 0) noexcept; void close() noexcept; + void clear() noexcept; + static void clear_storage(char const * name) noexcept; + bool wait(std::uint64_t tm = ipc::invalid_value) noexcept; bool post(std::uint32_t count = 1) noexcept; diff --git a/src/libipc/platform/linux/mutex.h b/src/libipc/platform/linux/mutex.h index 52956e1..6c684f0 100644 --- a/src/libipc/platform/linux/mutex.h +++ b/src/libipc/platform/linux/mutex.h @@ -136,7 +136,7 @@ class mutex { } template - void release_mutex(ipc::string const &name, F &&clear) { + static void release_mutex(ipc::string const &name, F &&clear) { if (name.empty()) return; auto &info = curr_prog::get(); IPC_UNUSED_ std::lock_guard guard {info.lock}; @@ -192,6 +192,23 @@ public: ref_ = nullptr; } + void clear() noexcept { + if (mutex_ != nullptr) { + if (mutex_->name() != nullptr) { + release_mutex(mutex_->name(), [] { return true; }); + } + mutex_->clear(); + } + mutex_ = nullptr; + ref_ = nullptr; + } + + static void clear_storage(char const *name) noexcept { + if (name == nullptr) return; + release_mutex(name, [] { return true; }); + robust_mutex::clear_storage(name); + } + bool lock(std::uint64_t tm) noexcept { if (!valid()) return false; return mutex_->lock(tm); diff --git a/src/libipc/platform/linux/sync_obj_impl.h b/src/libipc/platform/linux/sync_obj_impl.h index e28f95d..f7cb018 100644 --- a/src/libipc/platform/linux/sync_obj_impl.h +++ b/src/libipc/platform/linux/sync_obj_impl.h @@ -62,6 +62,15 @@ public: shm_.release(); h_ = nullptr; } + + void clear() noexcept { + shm_.clear(); // Make sure the storage is cleaned up. + h_ = nullptr; + } + + static void clear_storage(char const *name) noexcept { + ipc::shm::handle::clear_storage(name); + } }; } // namespace sync diff --git a/src/libipc/platform/posix/condition.h b/src/libipc/platform/posix/condition.h index d283d68..521f9fe 100644 --- a/src/libipc/platform/posix/condition.h +++ b/src/libipc/platform/posix/condition.h @@ -88,6 +88,21 @@ public: cond_ = nullptr; } + void clear() noexcept { + if ((shm_.ref() <= 1) && cond_ != nullptr) { + int eno; + if ((eno = ::pthread_cond_destroy(cond_)) != 0) { + ipc::error("fail pthread_cond_destroy[%d]\n", eno); + } + } + shm_.clear(); // Make sure the storage is cleaned up. + cond_ = nullptr; + } + + static void clear_storage(char const *name) noexcept { + ipc::shm::handle::clear_storage(name); + } + bool wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept { if (!valid()) return false; switch (tm) { diff --git a/src/libipc/platform/posix/mutex.h b/src/libipc/platform/posix/mutex.h index 9025b17..40284b0 100644 --- a/src/libipc/platform/posix/mutex.h +++ b/src/libipc/platform/posix/mutex.h @@ -71,7 +71,7 @@ class mutex { } template - void release_mutex(ipc::string const &name, F &&clear) { + static void release_mutex(ipc::string const &name, F &&clear) { if (name.empty()) return; auto &info = curr_prog::get(); IPC_UNUSED_ std::lock_guard guard {info.lock}; @@ -169,6 +169,30 @@ public: mutex_ = nullptr; } + void clear() noexcept { + if ((shm_ != nullptr) && (mutex_ != nullptr)) { + if (shm_->name() != nullptr) { + release_mutex(shm_->name(), [this] { + int eno; + if ((eno = ::pthread_mutex_destroy(mutex_)) != 0) { + ipc::error("fail pthread_mutex_destroy[%d]\n", eno); + } + return true; + }); + } + shm_->clear(); + } + shm_ = nullptr; + ref_ = nullptr; + mutex_ = nullptr; + } + + static void clear_storage(char const *name) noexcept { + if (name == nullptr) return; + release_mutex(name, [] { return true; }); + ipc::shm::handle::clear_storage(name); + } + bool lock(std::uint64_t tm) noexcept { if (!valid()) return false; for (;;) { diff --git a/src/libipc/platform/posix/semaphore_impl.h b/src/libipc/platform/posix/semaphore_impl.h index d48bcd4..0a33349 100644 --- a/src/libipc/platform/posix/semaphore_impl.h +++ b/src/libipc/platform/posix/semaphore_impl.h @@ -62,6 +62,24 @@ public: } } + void clear() noexcept { + if (valid()) { + if (::sem_close(h_) != 0) { + ipc::error("fail sem_close[%d]: %s\n", errno); + } + h_ = SEM_FAILED; + } + char const *name = shm_.name(); + if (name == nullptr) return; + ::sem_unlink(name); + shm_.clear(); // Make sure the storage is cleaned up. + } + + static void clear_storage(char const *name) noexcept { + ::sem_unlink(name); + ipc::shm::handle::clear_storage(name); + } + bool wait(std::uint64_t tm) noexcept { if (!valid()) return false; if (tm == invalid_value) { diff --git a/src/libipc/platform/posix/shm_posix.cpp b/src/libipc/platform/posix/shm_posix.cpp index 142fab4..74add01 100644 --- a/src/libipc/platform/posix/shm_posix.cpp +++ b/src/libipc/platform/posix/shm_posix.cpp @@ -188,7 +188,7 @@ void remove(id_t id) noexcept { } } -void remove(char const * name) { +void remove(char const * name) noexcept { if (!is_valid_string(name)) { ipc::error("fail remove: name is empty\n"); return; diff --git a/src/libipc/platform/win/condition.h b/src/libipc/platform/win/condition.h index 538aa08..9c89633 100644 --- a/src/libipc/platform/win/condition.h +++ b/src/libipc/platform/win/condition.h @@ -67,6 +67,16 @@ public: shm_.release(); } + void clear() noexcept { + close(); + } + + static void clear_storage(char const *name) noexcept { + ipc::shm::handle::clear_storage(name); + ipc::sync::mutex::clear_storage(name); + ipc::sync::semaphore::clear_storage(name); + } + bool wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept { if (!valid()) return false; auto &cnt = counter(); diff --git a/src/libipc/platform/win/mutex.h b/src/libipc/platform/win/mutex.h index c0cb543..e9b61cd 100644 --- a/src/libipc/platform/win/mutex.h +++ b/src/libipc/platform/win/mutex.h @@ -47,6 +47,13 @@ public: h_ = NULL; } + void clear() noexcept { + close(); + } + + static void clear_storage(char const */*name*/) noexcept { + } + bool lock(std::uint64_t tm) noexcept { DWORD ret, ms = (tm == invalid_value) ? INFINITE : static_cast(tm); for(;;) { diff --git a/src/libipc/platform/win/semaphore.h b/src/libipc/platform/win/semaphore.h index 5c44846..6cf94de 100644 --- a/src/libipc/platform/win/semaphore.h +++ b/src/libipc/platform/win/semaphore.h @@ -46,6 +46,13 @@ public: h_ = NULL; } + void clear() noexcept { + close(); + } + + static void clear_storage(char const */*name*/) noexcept { + } + bool wait(std::uint64_t tm) noexcept { DWORD ret, ms = (tm == invalid_value) ? INFINITE : static_cast(tm); switch ((ret = ::WaitForSingleObject(h_, ms))) { diff --git a/src/libipc/platform/win/shm_win.cpp b/src/libipc/platform/win/shm_win.cpp index 4b7016e..b19245f 100755 --- a/src/libipc/platform/win/shm_win.cpp +++ b/src/libipc/platform/win/shm_win.cpp @@ -102,7 +102,7 @@ void * get_mem(id_t id, std::size_t * size) { return static_cast(mem); } -std::int32_t release(id_t id) { +std::int32_t release(id_t id) noexcept { if (id == nullptr) { ipc::error("fail release: invalid id (null)\n"); return -1; @@ -120,7 +120,7 @@ std::int32_t release(id_t id) { return 0; } -void remove(id_t id) { +void remove(id_t id) noexcept { if (id == nullptr) { ipc::error("fail release: invalid id (null)\n"); return; @@ -128,7 +128,7 @@ void remove(id_t id) { release(id); } -void remove(char const * name) { +void remove(char const * name) noexcept { if (!is_valid_string(name)) { ipc::error("fail remove: name is empty\n"); return; diff --git a/src/libipc/sync/condition.cpp b/src/libipc/sync/condition.cpp index 36896a7..e64e688 100644 --- a/src/libipc/sync/condition.cpp +++ b/src/libipc/sync/condition.cpp @@ -61,6 +61,14 @@ void condition::close() noexcept { impl(p_)->cond_.close(); } +void condition::clear() noexcept { + impl(p_)->cond_.clear(); +} + +void condition::clear_storage(char const * name) noexcept { + ipc::detail::sync::condition::clear_storage(name); +} + bool condition::wait(ipc::sync::mutex &mtx, std::uint64_t tm) noexcept { return impl(p_)->cond_.wait(mtx, tm); } diff --git a/src/libipc/sync/mutex.cpp b/src/libipc/sync/mutex.cpp index 91bd0bb..c9c59f7 100644 --- a/src/libipc/sync/mutex.cpp +++ b/src/libipc/sync/mutex.cpp @@ -61,6 +61,14 @@ void mutex::close() noexcept { impl(p_)->lock_.close(); } +void mutex::clear() noexcept { + impl(p_)->lock_.clear(); +} + +void mutex::clear_storage(char const * name) noexcept { + ipc::detail::sync::mutex::clear_storage(name); +} + bool mutex::lock(std::uint64_t tm) noexcept { return impl(p_)->lock_.lock(tm); } diff --git a/src/libipc/sync/semaphore.cpp b/src/libipc/sync/semaphore.cpp index e58e8ec..ccb13c4 100644 --- a/src/libipc/sync/semaphore.cpp +++ b/src/libipc/sync/semaphore.cpp @@ -59,6 +59,14 @@ void semaphore::close() noexcept { impl(p_)->sem_.close(); } +void semaphore::clear() noexcept { + impl(p_)->sem_.clear(); +} + +void semaphore::clear_storage(char const * name) noexcept { + ipc::detail::sync::semaphore::clear_storage(name); +} + bool semaphore::wait(std::uint64_t tm) noexcept { return impl(p_)->sem_.wait(tm); }