From a2d918dec26bda0bb4cabe60ad08a3e9f445a6f4 Mon Sep 17 00:00:00 2001 From: zhangyi Date: Tue, 18 Jun 2019 19:29:58 +0800 Subject: [PATCH] try using ipc::string --- include/ipc.h | 15 +++----- src/ipc.cpp | 67 ++++++++++++++++++++++------------- src/memory/resource.h | 38 +++++++++++++++++--- src/memory/wrapper.h | 10 ++++-- src/platform/shm_linux.cpp | 8 +++-- src/platform/shm_win.cpp | 3 +- src/platform/to_tchar.h | 19 +++++++--- src/platform/waiter_linux.h | 7 ++-- src/platform/waiter_win.h | 13 +++---- src/platform/waiter_wrapper.h | 15 ++++---- src/shm.cpp | 3 +- 11 files changed, 132 insertions(+), 66 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index c8b339f..672ba7f 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - #include "export.h" #include "def.h" #include "buffer.h" @@ -23,6 +20,8 @@ struct IPC_EXPORT chan_impl { static handle_t connect (char const * name, unsigned mode); static void disconnect(handle_t h); + static char const * name(handle_t h); + static std::size_t recv_count(handle_t h); static bool wait_for_recv(handle_t h, std::size_t r_count, std::size_t tm); @@ -37,9 +36,7 @@ template class chan_wrapper { private: using detail_t = chan_impl; - - handle_t h_ = nullptr; - std::string n_; + handle_t h_ = nullptr; public: chan_wrapper() = default; @@ -58,7 +55,6 @@ public: void swap(chan_wrapper& rhs) { std::swap(h_, rhs.h_); - n_.swap(rhs.n_); } chan_wrapper& operator=(chan_wrapper rhs) { @@ -67,7 +63,7 @@ public: } char const * name() const { - return n_.c_str(); + return detail_t::name(h_); } handle_t handle() const { @@ -85,7 +81,7 @@ public: bool connect(char const * name, unsigned mode = sender | receiver) { if (name == nullptr || name[0] == '\0') return false; this->disconnect(); - h_ = detail_t::connect((n_ = name).c_str(), mode); + h_ = detail_t::connect(name, mode); return valid(); } @@ -93,7 +89,6 @@ public: if (!valid()) return; detail_t::disconnect(h_); h_ = nullptr; - n_.clear(); } std::size_t recv_count() const { diff --git a/src/ipc.cpp b/src/ipc.cpp index 1828dd7..594d02b 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -84,7 +84,19 @@ struct cache_t { } }; -auto& recv_cache() { +struct conn_info_head { + using acc_t = std::atomic; + + static auto cc_acc() { + static shm::handle acc_h("__CA_CONN__", sizeof(acc_t)); + return static_cast(acc_h.get()); + } + + ipc::string name_; + msg_id_t cc_id_; // connection-info id + waiter cc_waiter_, wt_waiter_, rd_waiter_; + shm::handle acc_h_; + /* thread_local may have some bugs. See: https://sourceforge.net/p/mingw-w64/bugs/727/ @@ -94,20 +106,7 @@ auto& recv_cache() { https://developercommunity.visualstudio.com/content/problem/124121/thread-local-variables-fail-to-be-initialized-when.html https://software.intel.com/en-us/forums/intel-c-compiler/topic/684827 */ - static tls::pointer> rc; - return *rc.create(); -} - -struct conn_info_head { - using acc_t = std::atomic; - - static auto acc() { - static shm::handle acc_h("__AC_CONN__", sizeof(acc_t)); - return static_cast(acc_h.get()); - } - - msg_id_t cc_id_; // connection-info id - waiter cc_waiter_, wt_waiter_, rd_waiter_; + tls::pointer> recv_cache_; struct simple_push { @@ -131,18 +130,28 @@ struct conn_info_head { circ::elem_array msg_datas_; conn_info_head(char const * name) - : cc_id_ ((acc() == nullptr) ? 0 : acc()->fetch_add(1, std::memory_order_relaxed)) - , cc_waiter_((std::string { "__CC_CONN__" } + name).c_str()) - , wt_waiter_((std::string { "__WT_CONN__" } + name).c_str()) - , rd_waiter_((std::string { "__RD_CONN__" } + name).c_str()) { + : name_ (name) + , cc_id_ ((cc_acc() == nullptr) ? 0 : cc_acc()->fetch_add(1, std::memory_order_relaxed)) + , cc_waiter_(("__CC_CONN__" + name_).c_str()) + , wt_waiter_(("__WT_CONN__" + name_).c_str()) + , rd_waiter_(("__RD_CONN__" + name_).c_str()) + , acc_h_ (("__AC_CONN__" + name_).c_str(), sizeof(acc_t)) { + } + + auto acc() { + return static_cast(acc_h_.get()); + } + + auto& recv_cache() { + return *recv_cache_.create(); } static shm::id_t apply_storage(msg_id_t msg_id, std::size_t size) { - return shm::acquire(("__ST_CONN__" + std::to_string(msg_id)).c_str(), size, shm::create); + return shm::acquire(("__ST_CONN__" + ipc::to_string(msg_id)).c_str(), size, shm::create); } static shm::id_t apply_storage(msg_id_t msg_id) { - return shm::acquire(("__ST_CONN__" + std::to_string(msg_id)).c_str(), 0, shm::open); + return shm::acquire(("__ST_CONN__" + ipc::to_string(msg_id)).c_str(), 0, shm::open); } void store(shm::id_t dat) { @@ -153,7 +162,9 @@ struct conn_info_head { void clear_store() { msg_datas_.push([](shm::id_t * id) { - if (*id != nullptr) shm::remove(*id); + if (*id == nullptr) return; + shm::remove(*id); + (*id) = nullptr; }); } }; @@ -189,8 +200,8 @@ struct queue_generator { conn_info_t(char const * name) : conn_info_head(name) , que_(("__QU_CONN__" + - std::to_string(DataSize ) + "__" + - std::to_string(AlignSize) + "__" + name).c_str()) { + ipc::to_string(DataSize) + "__" + + ipc::to_string(AlignSize) + "__" + name).c_str()) { } }; }; @@ -345,7 +356,7 @@ static buff_t recv(ipc::handle_t h, std::size_t tm) { if (que->connect()) { // wouldn't connect twice info_of(h)->cc_waiter_.broadcast(); } - auto& rc = recv_cache(); + auto& rc = info_of(h)->recv_cache(); while (1) { // pop a new message typename queue_t::value_t msg; @@ -430,6 +441,12 @@ void chan_impl::disconnect(ipc::handle_t h) { detail_impl>::disconnect(h); } +template +char const * chan_impl::name(ipc::handle_t h) { + auto info = detail_impl>::info_of(h); + return (info == nullptr) ? nullptr : info->name_.c_str(); +} + template std::size_t chan_impl::recv_count(ipc::handle_t h) { return detail_impl>::recv_count(h); diff --git a/src/memory/resource.h b/src/memory/resource.h index dfeacfb..72d4718 100644 --- a/src/memory/resource.h +++ b/src/memory/resource.h @@ -5,7 +5,8 @@ #include #include #include -#include +#include +#include #include "def.h" @@ -28,13 +29,42 @@ using sync_pool_alloc = mem::detail::pool_alloc; template using allocator = allocator_wrapper; +} // namespace mem + +namespace { + +constexpr char const * pf(int) { return "%d" ; } +constexpr char const * pf(long) { return "%ld" ; } +constexpr char const * pf(long long) { return "%lld"; } +constexpr char const * pf(unsigned int) { return "%u" ; } +constexpr char const * pf(unsigned long) { return "%lu" ; } +constexpr char const * pf(unsigned long long) { return "%llu"; } +constexpr char const * pf(float) { return "%f" ; } +constexpr char const * pf(double) { return "%f" ; } +constexpr char const * pf(long double) { return "%Lf" ; } + +} // internal-linkage + template using unordered_map = std::unordered_map< - Key, T, std::hash, std::equal_to, allocator> + Key, T, std::hash, std::equal_to, ipc::mem::allocator> +>; + +using string = std::basic_string< + char, std::char_traits, ipc::mem::allocator +>; + +using wstring = std::basic_string< + wchar_t, std::char_traits, ipc::mem::allocator >; template -using vector = std::vector>; +ipc::string to_string(T val) { + char buf[std::numeric_limits::digits10 + 1] {}; + if (std::snprintf(buf, sizeof(buf), pf(val), val) > 0) { + return buf; + } + return {}; +} -} // namespace mem } // namespace ipc diff --git a/src/memory/wrapper.h b/src/memory/wrapper.h index 1d5b61c..6d602ac 100644 --- a/src/memory/wrapper.h +++ b/src/memory/wrapper.h @@ -36,6 +36,7 @@ public: typedef value_type& reference; typedef const value_type& const_reference; typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; typedef AllocP alloc_policy; private: @@ -103,8 +104,13 @@ public: template class allocator_wrapper { public: - typedef void value_type; - typedef AllocP alloc_policy; + // type definitions + typedef void value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef AllocP alloc_policy; }; template diff --git a/src/platform/shm_linux.cpp b/src/platform/shm_linux.cpp index 84fbc51..42dbc23 100644 --- a/src/platform/shm_linux.cpp +++ b/src/platform/shm_linux.cpp @@ -17,6 +17,8 @@ #include "log.h" #include "pool_alloc.h" +#include "memory/resource.h" + namespace { struct info_t { @@ -27,7 +29,7 @@ struct id_info_t { int fd_ = -1; void* mem_ = nullptr; std::size_t size_ = 0; - std::string name_; + ipc::string name_; }; constexpr std::size_t calc_size(std::size_t size) { @@ -48,7 +50,7 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) { ipc::error("fail acquire: name is empty\n"); return nullptr; } - std::string op_name = std::string{"__IPC_SHM__"} + name; + ipc::string op_name = ipc::string{"__IPC_SHM__"} + name; // Open the object for read-write access. int flag = O_RDWR; switch (mode) { @@ -163,7 +165,7 @@ void remove(char const * name) { ipc::error("fail remove: name is empty\n"); return; } - ::shm_unlink((std::string{"__IPC_SHM__"} + name).c_str()); + ::shm_unlink((ipc::string{"__IPC_SHM__"} + name).c_str()); } } // namespace shm diff --git a/src/platform/shm_win.cpp b/src/platform/shm_win.cpp index 52e0cd3..5343473 100644 --- a/src/platform/shm_win.cpp +++ b/src/platform/shm_win.cpp @@ -10,6 +10,7 @@ #include "pool_alloc.h" #include "platform/to_tchar.h" +#include "memory/resource.h" namespace { @@ -30,7 +31,7 @@ id_t acquire(char const * name, std::size_t size, unsigned mode) { return nullptr; } HANDLE h; - auto fmt_name = ipc::detail::to_tchar(std::string{"__IPC_SHM__"} + name); + auto fmt_name = ipc::detail::to_tchar(ipc::string{"__IPC_SHM__"} + name); // Opens a named file mapping object. if (mode == open) { h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, fmt_name.c_str()); diff --git a/src/platform/to_tchar.h b/src/platform/to_tchar.h index 9e4b49c..57afed1 100644 --- a/src/platform/to_tchar.h +++ b/src/platform/to_tchar.h @@ -11,6 +11,7 @@ #include "concept.h" #include "platform/detail.h" +#include "memory/resource.h" namespace ipc::detail { @@ -33,13 +34,18 @@ using IsSameChar = ipc::Requires::value, R>; //////////////////////////////////////////////////////////////// template -constexpr auto to_tchar(std::string && str) -> IsSameChar { +constexpr auto to_tchar(ipc::string && str) -> IsSameChar { return std::move(str); } template -constexpr auto to_tchar(std::string && str) -> IsSameChar { - return std::wstring_convert>{}.from_bytes(std::move(str)); +constexpr auto to_tchar(ipc::string && str) -> IsSameChar { + return std::wstring_convert< + std::codecvt_utf8_utf16, + wchar_t, + ipc::mem::allocator, + ipc::mem::allocator + >{}.from_bytes(std::move(str)); } template @@ -49,7 +55,12 @@ inline auto to_tchar(T* dst, char const * src, std::size_t size) -> IsSameChar inline auto to_tchar(T* dst, char const * src, std::size_t size) -> IsSameChar { - auto wstr = std::wstring_convert>{}.from_bytes(src, src + size); + auto wstr = std::wstring_convert< + std::codecvt_utf8_utf16, + wchar_t, + ipc::mem::allocator, + ipc::mem::allocator + >{}.from_bytes(src, src + size); std::memcpy(dst, wstr.data(), (ipc::detail::min)(wstr.size(), size)); } diff --git a/src/platform/waiter_linux.h b/src/platform/waiter_linux.h index 07b13dd..f53c113 100644 --- a/src/platform/waiter_linux.h +++ b/src/platform/waiter_linux.h @@ -14,6 +14,7 @@ #include "log.h" #include "platform/detail.h" +#include "memory/resource.h" namespace ipc { namespace detail { @@ -209,13 +210,13 @@ class waiter_helper { long counter_ = 0; public: - using handle_t = std::tuple; + using handle_t = std::tuple; static handle_t invalid() noexcept { - return std::make_tuple(std::string{}, sem_helper::invalid(), sem_helper::invalid()); + return std::make_tuple(ipc::string{}, sem_helper::invalid(), sem_helper::invalid()); } - handle_t open_h(std::string && name) { + handle_t open_h(ipc::string && name) { auto sem = sem_helper::open(("__WAITER_HELPER_SEM__" + name).c_str(), 0); if (sem == sem_helper::invalid()) { return invalid(); diff --git a/src/platform/waiter_win.h b/src/platform/waiter_win.h index 9b3a1fd..4935dd5 100644 --- a/src/platform/waiter_win.h +++ b/src/platform/waiter_win.h @@ -12,6 +12,7 @@ #include "platform/to_tchar.h" #include "platform/detail.h" +#include "memory/resource.h" namespace ipc { namespace detail { @@ -22,7 +23,7 @@ class semaphore { public: static void remove(char const * /*name*/) {} - bool open(std::string && name, long count = 0, long limit = LONG_MAX) { + bool open(ipc::string && name, long count = 0, long limit = LONG_MAX) { h_ = ::CreateSemaphore(NULL, count, limit, ipc::detail::to_tchar(std::move(name)).c_str()); if (h_ == NULL) { ipc::error("fail CreateSemaphore[%lu]: %s\n", ::GetLastError(), name.c_str()); @@ -62,7 +63,7 @@ class mutex : public semaphore { using semaphore::post; public: - bool open(std::string && name) { + bool open(ipc::string && name) { return semaphore::open(std::move(name), 1, 1); } @@ -87,12 +88,12 @@ public: } static void remove(char const * name) { - semaphore::remove((std::string{ "__COND_HAN__" } + name).c_str()); - semaphore::remove((std::string{ "__COND_SEM__" } + name).c_str()); - mutex ::remove((std::string{ "__COND_MTX__" } + name).c_str()); + semaphore::remove((ipc::string{ "__COND_HAN__" } + name).c_str()); + semaphore::remove((ipc::string{ "__COND_SEM__" } + name).c_str()); + mutex ::remove((ipc::string{ "__COND_MTX__" } + name).c_str()); } - bool open(std::string const & name, std::atomic * waiting, long * counter) { + bool open(ipc::string const & name, std::atomic * waiting, long * counter) { if (lock_ .open("__COND_MTX__" + name) && sema_ .open("__COND_SEM__" + name) && handshake_.open("__COND_HAN__" + name)) { diff --git a/src/platform/waiter_wrapper.h b/src/platform/waiter_wrapper.h index 7a11cd8..a0259db 100644 --- a/src/platform/waiter_wrapper.h +++ b/src/platform/waiter_wrapper.h @@ -6,6 +6,7 @@ #include "shm.h" +#include "memory/resource.h" #include "platform/detail.h" #if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || \ defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ @@ -26,12 +27,12 @@ class condition_impl : public ipc::detail::condition { public: static void remove(char const * name) { ipc::detail::condition::remove(name); - std::string n = name; + ipc::string n = name; ipc::shm::remove((n + "__COND_CNT__" ).c_str()); ipc::shm::remove((n + "__COND_WAIT__").c_str()); } - bool open(std::string const & name) { + bool open(ipc::string const & name) { if (wait_h_.acquire((name + "__COND_WAIT__").c_str(), sizeof(std::atomic)) && cnt_h_ .acquire((name + "__COND_CNT__" ).c_str(), sizeof(long))) { return ipc::detail::condition::open(name, @@ -129,7 +130,7 @@ public: class semaphore_impl { sem_helper::handle_t h_; ipc::shm::handle opened_; // std::atomic - std::string name_; + ipc::string name_; auto cnt() { return static_cast*>(opened_.get()); @@ -137,8 +138,8 @@ class semaphore_impl { public: static void remove(char const * name) { - sem_helper::destroy((std::string{ "__SEMAPHORE_IMPL_SEM__" } + name).c_str()); - ipc::shm::remove ((std::string{ "__SEMAPHORE_IMPL_CNT__" } + name).c_str()); + sem_helper::destroy((ipc::string{ "__SEMAPHORE_IMPL_SEM__" } + name).c_str()); + ipc::shm::remove ((ipc::string{ "__SEMAPHORE_IMPL_CNT__" } + name).c_str()); } bool open(char const * name, long count) { @@ -269,11 +270,11 @@ public: return false; } close(); - if (!shm_.acquire((std::string{ "__SHM_WAITER__" } + name).c_str(), sizeof(waiter_t))) { + if (!shm_.acquire((ipc::string{ "__SHM_WAITER__" } + name).c_str(), sizeof(waiter_t))) { return false; } attach(static_cast(shm_.get())); - return detail::waiter_wrapper::open((std::string{ "__IMP_WAITER__" } + name).c_str()); + return detail::waiter_wrapper::open((ipc::string{ "__IMP_WAITER__" } + name).c_str()); } void close() { diff --git a/src/shm.cpp b/src/shm.cpp index f8cd2a1..7a3c7e5 100644 --- a/src/shm.cpp +++ b/src/shm.cpp @@ -4,6 +4,7 @@ #include #include "pimpl.h" +#include "memory/resource.h" namespace ipc { namespace shm { @@ -13,7 +14,7 @@ public: shm::id_t id_ = nullptr; void* m_ = nullptr; - std::string n_; + ipc::string n_; std::size_t s_ = 0; };