diff --git a/include/libipc/ipc.h b/include/libipc/ipc.h index 64b262c9..882367c8 100755 --- a/include/libipc/ipc.h +++ b/include/libipc/ipc.h @@ -19,6 +19,8 @@ enum : unsigned { template struct IPC_EXPORT chan_impl { + static ipc::handle_t inited(); + static bool connect (ipc::handle_t * ph, char const * name, unsigned mode); static bool reconnect (ipc::handle_t * ph, unsigned mode); static void disconnect(ipc::handle_t h); @@ -41,7 +43,7 @@ class chan_wrapper { private: using detail_t = chan_impl; - ipc::handle_t h_ = nullptr; + ipc::handle_t h_ = detail_t::inited(); unsigned mode_ = ipc::sender; bool connected_ = false; diff --git a/src/libipc/ipc.cpp b/src/libipc/ipc.cpp index c864a1b1..4dc71c07 100755 --- a/src/libipc/ipc.cpp +++ b/src/libipc/ipc.cpp @@ -630,6 +630,12 @@ using policy_t = ipc::policy::choose; namespace ipc { +template +ipc::handle_t chan_impl::inited() { + ipc::detail::waiter::init(); + return nullptr; +} + template bool chan_impl::connect(ipc::handle_t * ph, char const * name, unsigned mode) { return detail_impl>::connect(ph, name, mode & receiver); diff --git a/src/libipc/platform/linux/mutex.h b/src/libipc/platform/linux/mutex.h index 91f156b4..d64972ea 100644 --- a/src/libipc/platform/linux/mutex.h +++ b/src/libipc/platform/linux/mutex.h @@ -125,8 +125,8 @@ class mutex { IPC_UNUSED_ std::lock_guard guard {info.lock}; auto it = info.mutex_handles.find(name); if (it == info.mutex_handles.end()) { - it = curr_prog::get().mutex_handles.emplace(name, - curr_prog::shm_data::init{name}).first; + it = info.mutex_handles.emplace(name, + curr_prog::shm_data::init{name}).first; } mutex_ = &it->second.mtx; ref_ = &it->second.ref; @@ -135,13 +135,14 @@ class mutex { template void release_mutex(ipc::string const &name, F &&clear) { if (name.empty()) return; - IPC_UNUSED_ std::lock_guard guard {curr_prog::get().lock}; - auto it = curr_prog::get().mutex_handles.find(name); - if (it == curr_prog::get().mutex_handles.end()) { + auto &info = curr_prog::get(); + IPC_UNUSED_ std::lock_guard guard {info.lock}; + auto it = info.mutex_handles.find(name); + if (it == info.mutex_handles.end()) { return; } if (clear()) { - curr_prog::get().mutex_handles.erase(it); + info.mutex_handles.erase(it); } } @@ -149,6 +150,11 @@ class mutex { mutex() = default; ~mutex() = default; + static void init() { + // Avoid exception problems caused by static member initialization order. + curr_prog::get(); + } + a0_mtx_t const *native() const noexcept { return valid() ? mutex_->native() : nullptr; } diff --git a/src/libipc/platform/posix/mutex.h b/src/libipc/platform/posix/mutex.h index 8f7525f0..b17092c0 100644 --- a/src/libipc/platform/posix/mutex.h +++ b/src/libipc/platform/posix/mutex.h @@ -55,8 +55,8 @@ class mutex { IPC_UNUSED_ std::lock_guard guard {info.lock}; auto it = info.mutex_handles.find(name); if (it == info.mutex_handles.end()) { - it = curr_prog::get().mutex_handles.emplace(name, - curr_prog::shm_data::init{name, sizeof(pthread_mutex_t)}).first; + it = info.mutex_handles.emplace(name, + curr_prog::shm_data::init{name, sizeof(pthread_mutex_t)}).first; } shm_ = &it->second.shm; ref_ = &it->second.ref; @@ -69,20 +69,32 @@ class mutex { template void release_mutex(ipc::string const &name, F &&clear) { if (name.empty()) return; - IPC_UNUSED_ std::lock_guard guard {curr_prog::get().lock}; - auto it = curr_prog::get().mutex_handles.find(name); - if (it == curr_prog::get().mutex_handles.end()) { + auto &info = curr_prog::get(); + IPC_UNUSED_ std::lock_guard guard {info.lock}; + auto it = info.mutex_handles.find(name); + if (it == info.mutex_handles.end()) { return; } if (clear()) { - curr_prog::get().mutex_handles.erase(it); + info.mutex_handles.erase(it); } } + static pthread_mutex_t const &zero_mem() { + static const pthread_mutex_t tmp{}; + return tmp; + } + public: mutex() = default; ~mutex() = default; + static void init() { + // Avoid exception problems caused by static member initialization order. + zero_mem(); + curr_prog::get(); + } + pthread_mutex_t const *native() const noexcept { return mutex_; } @@ -92,9 +104,8 @@ class mutex { } bool valid() const noexcept { - static const char tmp[sizeof(pthread_mutex_t)] {}; return (shm_ != nullptr) && (ref_ != nullptr) && (mutex_ != nullptr) - && (std::memcmp(tmp, mutex_, sizeof(pthread_mutex_t)) != 0); + && (std::memcmp(&zero_mem(), mutex_, sizeof(pthread_mutex_t)) != 0); } bool open(char const *name) noexcept { diff --git a/src/libipc/platform/win/mutex.h b/src/libipc/platform/win/mutex.h index 68968c48..8ecaf476 100644 --- a/src/libipc/platform/win/mutex.h +++ b/src/libipc/platform/win/mutex.h @@ -21,6 +21,8 @@ class mutex { mutex() noexcept = default; ~mutex() noexcept = default; + static void init() {} + HANDLE native() const noexcept { return h_; } diff --git a/src/libipc/sync/waiter.cpp b/src/libipc/sync/waiter.cpp new file mode 100644 index 00000000..3a04abfe --- /dev/null +++ b/src/libipc/sync/waiter.cpp @@ -0,0 +1,22 @@ +#include "libipc/waiter.h" + +#include "libipc/platform/detail.h" +#if defined(IPC_OS_WINDOWS_) +#include "libipc/platform/win/mutex.h" +#elif defined(IPC_OS_LINUX_) +#include "libipc/platform/linux/mutex.h" +#elif defined(IPC_OS_QNX_) +#include "libipc/platform/posix/mutex.h" +#else/*IPC_OS*/ +# error "Unsupported platform." +#endif + +namespace ipc { +namespace detail { + +void waiter::init() { + ipc::detail::sync::mutex::init(); +} + +} // namespace detail +} // namespace ipc diff --git a/src/libipc/waiter.h b/src/libipc/waiter.h index 2e13dc39..ee45fe35 100644 --- a/src/libipc/waiter.h +++ b/src/libipc/waiter.h @@ -19,6 +19,8 @@ class waiter { std::atomic quit_ {false}; public: + static void init(); + waiter() = default; waiter(char const *name) { open(name);