From cca4664e840c019c1656a02219ae6e0ee3b63e33 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sat, 10 Jul 2021 13:50:46 +0800 Subject: [PATCH 1/3] option(LIBIPC_BUILD_SHARED_LIBS 'Build shared libraries (DLLs).' OFF) --- CMakeLists.txt | 12 ++++++------ include/libipc/export.h | 6 ++++-- src/CMakeLists.txt | 18 ++++++++++++++---- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 57f62e7..56a6fac 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ option(LIBIPC_BUILD_DEMOS "Build all of libipc's own demos." OFF) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") if(NOT MSVC) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") endif() include_directories(${CMAKE_SOURCE_DIR}/include) @@ -19,14 +19,14 @@ set(LIBIPC_PROJECT_DIR ${PROJECT_SOURCE_DIR}) add_subdirectory(src) if (LIBIPC_BUILD_TESTS) - set(GOOGLETEST_VERSION 1.10.0) - add_subdirectory(3rdparty/gtest) - add_subdirectory(test) + set(GOOGLETEST_VERSION 1.10.0) + add_subdirectory(3rdparty/gtest) + add_subdirectory(test) endif() if (LIBIPC_BUILD_DEMOS) - add_subdirectory(demo/chat) - add_subdirectory(demo/msg_que) + add_subdirectory(demo/chat) + add_subdirectory(demo/msg_que) endif() install( diff --git a/include/libipc/export.h b/include/libipc/export.h index c555574..6024f2f 100755 --- a/include/libipc/export.h +++ b/include/libipc/export.h @@ -44,9 +44,11 @@ */ #ifndef IPC_EXPORT -#if defined(__IPC_LIBRARY__) +#if defined(LIBIPC_LIBRARY_SHARED_BUILDING__) # define IPC_EXPORT IPC_DECL_EXPORT -#else +#elif defined(LIBIPC_LIBRARY_SHARED_USING__) # define IPC_EXPORT IPC_DECL_IMPORT +#else +# define IPC_EXPORT #endif #endif /*IPC_EXPORT*/ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 08faf05..143f9de 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ project(ipc) -add_compile_options(-D__IPC_LIBRARY__) +option(LIBIPC_BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF) if(NOT MSVC) add_compile_options(-fPIC) @@ -26,11 +26,21 @@ file(GLOB HEAD_FILES ${LIBIPC_PROJECT_DIR}/src/libipc/platform/*.h ${LIBIPC_PROJECT_DIR}/src/libipc/utility/*.h) -add_library(${PROJECT_NAME} SHARED ${SRC_FILES} ${HEAD_FILES}) +if (LIBIPC_BUILD_SHARED_LIBS) + add_library(${PROJECT_NAME} SHARED ${SRC_FILES} ${HEAD_FILES}) + target_compile_definitions(${PROJECT_NAME} + INTERFACE + LIBIPC_LIBRARY_SHARED_USING__ + PRIVATE + LIBIPC_LIBRARY_SHARED_BUILDING__) +else() + add_library(${PROJECT_NAME} STATIC ${SRC_FILES} ${HEAD_FILES}) +endif() + if(NOT MSVC) target_link_libraries(${PROJECT_NAME} PUBLIC - pthread - $<$>:rt>) + pthread + $<$>:rt>) endif() install( From a97b12f71dd260e07d9d19311d1836c1e691c76c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Sat, 10 Jul 2021 13:52:44 +0800 Subject: [PATCH 2/3] Update c-cpp.yml --- .github/workflows/c-cpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 3ca4d7e..c5542c8 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -2,7 +2,7 @@ name: C/C++ CI on: push: - branches: [ master, develop ] + branches: [ master, develop, issue-* ] pull_request: branches: [ master, develop ] From 69e1586b5adbb3578cd68f82d0578d390017ddc1 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sat, 10 Jul 2021 14:22:31 +0800 Subject: [PATCH 3/3] remove tls --- include/libipc/tls_pointer.h | 112 ------------------------ src/ipc.cpp | 17 +--- src/libipc/memory/wrapper.h | 7 +- src/libipc/platform/tls_detail_win.h | 41 --------- src/libipc/platform/tls_pointer_linux.h | 83 ------------------ src/libipc/platform/tls_pointer_win.cpp | 100 --------------------- src/libipc/platform/tls_pointer_win.h | 46 ---------- src/tls_pointer.cpp | 8 -- test/test_thread_utility.cpp | 5 +- 9 files changed, 7 insertions(+), 412 deletions(-) delete mode 100755 include/libipc/tls_pointer.h delete mode 100755 src/libipc/platform/tls_detail_win.h delete mode 100755 src/libipc/platform/tls_pointer_linux.h delete mode 100755 src/libipc/platform/tls_pointer_win.cpp delete mode 100755 src/libipc/platform/tls_pointer_win.h delete mode 100755 src/tls_pointer.cpp diff --git a/include/libipc/tls_pointer.h b/include/libipc/tls_pointer.h deleted file mode 100755 index b6fd4e1..0000000 --- a/include/libipc/tls_pointer.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -#include // std::unique_ptr -#include // std::forward -#include // std::size_t - -#include "libipc/export.h" - -namespace ipc { -namespace tls { - -using key_t = std::size_t; -using destructor_t = void (*)(void *); - -struct key_info { - key_t key_; -}; - -IPC_EXPORT bool create (key_info * pkey, destructor_t destructor = nullptr); -IPC_EXPORT void release(key_info const * pkey); - -IPC_EXPORT bool set(key_info const * pkey, void * ptr); -IPC_EXPORT void * get(key_info const * pkey); - -//////////////////////////////////////////////////////////////// -/// Thread-local pointer -//////////////////////////////////////////////////////////////// - -/** - * @remarks - * You need to set the ipc::tls::pointer's storage manually: - * ``` - * tls::pointer p; - * if (!p) p = new int(123); - * ``` - * It would be like an ordinary pointer. - * Or you could just call create_once to 'new' this pointer automatically. - * ``` - * tls::pointer p; - * p.create_once(123); - * ``` -*/ - -template -class pointer : public key_info { - - pointer(pointer const &) = delete; - pointer & operator=(pointer const &) = delete; - - void destruct() const { - delete static_cast(tls::get(this)); - } - -public: - using value_type = T; - - pointer() { - tls::create(this, [](void* p) { - delete static_cast(p); - }); - } - - ~pointer() { - destruct(); - tls::release(this); - } - - template - T* create(P&&... params) { - destruct(); - std::unique_ptr ptr { new T(std::forward

(params)...) }; - if (!tls::set(this, ptr.get())) { - return nullptr; - } - return ptr.release(); - } - - template - T* create_once(P&&... params) { - auto p = static_cast(tls::get(this)); - if (p == nullptr) { - std::unique_ptr ptr { new T(std::forward

(params)...) }; - if (!tls::set(this, ptr.get())) { - return nullptr; - } - p = ptr.release(); - } - return p; - } - - T* operator=(T* p) { - set(this, p); - return p; - } - - explicit operator T *() const { - return static_cast(tls::get(this)); - } - - explicit operator bool() const { - return tls::get(this) != nullptr; - } - - T & operator* () { return *static_cast(*this); } - const T & operator* () const { return *static_cast(*this); } - - T * operator->() { return static_cast(*this); } - const T * operator->() const { return static_cast(*this); } -}; - -} // namespace tls -} // namespace ipc diff --git a/src/ipc.cpp b/src/ipc.cpp index 12a629b..8b18dde 100755 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -13,7 +13,6 @@ #include "libipc/ipc.h" #include "libipc/def.h" #include "libipc/shm.h" -#include "libipc/tls_pointer.h" #include "libipc/pool_alloc.h" #include "libipc/queue.h" #include "libipc/policy.h" @@ -253,19 +252,6 @@ struct conn_info_head { ipc::waiter cc_waiter_, wt_waiter_, rd_waiter_; ipc::shm::handle acc_h_; - /* - * thread_local may have some bugs. - * - * - * - https://sourceforge.net/p/mingw-w64/bugs/727/ - * - https://sourceforge.net/p/mingw-w64/bugs/527/ - * - https://github.com/Alexpux/MINGW-packages/issues/2519 - * - https://github.com/ChaiScript/ChaiScript/issues/402 - * - 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 - */ - ipc::tls::pointer> recv_cache_; - conn_info_head(char const * name) : name_ {name} , cc_id_ {(cc_acc() == nullptr) ? 0 : cc_acc()->fetch_add(1, std::memory_order_relaxed)} @@ -286,7 +272,8 @@ struct conn_info_head { } auto& recv_cache() { - return *recv_cache_.create_once(); + thread_local ipc::unordered_map tls; + return tls; } }; diff --git a/src/libipc/memory/wrapper.h b/src/libipc/memory/wrapper.h index 5e76f88..b0b7c58 100755 --- a/src/libipc/memory/wrapper.h +++ b/src/libipc/memory/wrapper.h @@ -11,7 +11,6 @@ #include "libipc/def.h" #include "libipc/rw_lock.h" -#include "libipc/tls_pointer.h" #include "libipc/pool_alloc.h" #include "libipc/utility/concept.h" @@ -155,18 +154,16 @@ private: }; friend class alloc_proxy; - using ref_t = alloc_proxy&; - using tls_t = tls::pointer; - tls_t tls_; std::function get_alloc_; public: template async_wrapper(P ... pars) { get_alloc_ = [this, pars ...]()->ref_t { - return *tls_.create_once(this, pars ...); + thread_local alloc_proxy tls(pars ...); + return tls; }; } diff --git a/src/libipc/platform/tls_detail_win.h b/src/libipc/platform/tls_detail_win.h deleted file mode 100755 index 27b9f14..0000000 --- a/src/libipc/platform/tls_detail_win.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include // std::unordered_map -#include // assert - -#include "libipc/tls_pointer.h" - -#include "libipc/utility/utility.h" - -namespace ipc { -namespace tls { - -inline void tls_destruct(key_info const * pkey, void * p) { - assert(pkey != nullptr); - auto destructor = horrible_cast(pkey->key_); - if (destructor != nullptr) destructor(p); -} - -struct tls_recs : public std::unordered_map { - ~tls_recs() { - for (auto & pair : *this) { - tls_destruct(pair.first, pair.second); - } - } -}; - -inline tls_recs * tls_get_recs() { - thread_local tls_recs * recs_ptr = nullptr; - if (recs_ptr == nullptr) { - recs_ptr = new tls_recs; - } - assert(recs_ptr != nullptr); - return recs_ptr; -} - -inline void at_thread_exit() { - delete tls_get_recs(); -} - -} // namespace tls -} // namespace ipc diff --git a/src/libipc/platform/tls_pointer_linux.h b/src/libipc/platform/tls_pointer_linux.h deleted file mode 100755 index 21ab44b..0000000 --- a/src/libipc/platform/tls_pointer_linux.h +++ /dev/null @@ -1,83 +0,0 @@ - -#include // pthread_... - -#include // std::atomic_thread_fence -#include // assert - -#include "libipc/tls_pointer.h" - -#include "libipc/utility/log.h" -#include "libipc/utility/utility.h" - -namespace ipc { -namespace tls { - -namespace { -namespace native { - -using key_t = pthread_key_t; - -bool create(key_t * pkey, void (*destructor)(void*)) { - assert(pkey != nullptr); - int err = ::pthread_key_create(pkey, destructor); - if (err != 0) { - ipc::error("[native::create] pthread_key_create failed [%d].\n", err); - return false; - } - return true; -} - -bool release(key_t key) { - int err = ::pthread_key_delete(key); - if (err != 0) { - ipc::error("[native::release] pthread_key_delete failed [%d].\n", err); - return false; - } - return true; -} - -bool set(key_t key, void * ptr) { - int err = ::pthread_setspecific(key, ptr); - if (err != 0) { - ipc::error("[native::set] pthread_setspecific failed [%d].\n", err); - return false; - } - return true; -} - -void * get(key_t key) { - return ::pthread_getspecific(key); -} - -} // namespace native -} // internal-linkage - -bool create(key_info * pkey, destructor_t destructor) { - assert(pkey != nullptr); - native::key_t k; - if (!native::create(&k, destructor)) { - return false; - } - pkey->key_ = horrible_cast(k); - std::atomic_thread_fence(std::memory_order_seq_cst); - return true; -} - -void release(key_info const * pkey) { - assert(pkey != nullptr); - static_cast( - native::release(horrible_cast(pkey->key_))); -} - -bool set(key_info const * pkey, void* ptr) { - assert(pkey != nullptr); - return native::set(horrible_cast(pkey->key_), ptr); -} - -void * get(key_info const * pkey) { - assert(pkey != nullptr); - return native::get(horrible_cast(pkey->key_)); -} - -} // namespace tls -} // namespace ipc diff --git a/src/libipc/platform/tls_pointer_win.cpp b/src/libipc/platform/tls_pointer_win.cpp deleted file mode 100755 index cdbe208..0000000 --- a/src/libipc/platform/tls_pointer_win.cpp +++ /dev/null @@ -1,100 +0,0 @@ - -#include - -#include "libipc/platform/tls_detail_win.h" - -/** - * @remarks - * Windows doesn't support a per-thread destructor with its TLS primitives. - * So, here will build it manually by inserting a function to be called on each thread's exit. - * - * @see - * - https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way - * - https://src.chromium.org/viewvc/chrome/trunk/src/base/threading/thread_local_storage_win.cc - * - https://github.com/mirror/mingw-org-wsl/blob/master/src/libcrt/crt/tlssup.c - * - https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-crt/crt/tlssup.c - * - http://svn.boost.org/svn/boost/trunk/libs/thread/src/win32/tss_pe.cpp -*/ - -namespace ipc { -namespace tls { - -namespace { - -void NTAPI OnTlsCallback(PVOID, DWORD dwReason, PVOID) { - if (dwReason == DLL_THREAD_DETACH) { - ipc::tls::at_thread_exit(); - } -} - -} // internal-linkage - -//////////////////////////////////////////////////////////////// -/// Call destructors on thread exit -//////////////////////////////////////////////////////////////// - -#if defined(_MSC_VER) - -#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) - -#pragma comment(linker, "/INCLUDE:_tls_used") -#pragma comment(linker, "/INCLUDE:_tls_xl_b__") - -extern "C" { -# pragma const_seg(".CRT$XLB") - extern const PIMAGE_TLS_CALLBACK _tls_xl_b__; - const PIMAGE_TLS_CALLBACK _tls_xl_b__ = OnTlsCallback; -# pragma const_seg() -} - -#else /*!WIN64*/ - -#pragma comment(linker, "/INCLUDE:__tls_used") -#pragma comment(linker, "/INCLUDE:__tls_xl_b__") - -extern "C" { -# pragma data_seg(".CRT$XLB") - PIMAGE_TLS_CALLBACK _tls_xl_b__ = OnTlsCallback; -# pragma data_seg() -} - -#endif/*!WIN64*/ - -#elif defined(__GNUC__) - -#define IPC_CRTALLOC__(x) __attribute__ ((section (x) )) - -#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || \ - (__MINGW32_MAJOR_VERSION > 3) || ((__MINGW32_MAJOR_VERSION == 3) && (__MINGW32_MINOR_VERSION >= 18)) - -extern "C" { - IPC_CRTALLOC__(".CRT$XLB") PIMAGE_TLS_CALLBACK _tls_xl_b__ = OnTlsCallback; -} - -#else /*!MINGW*/ - -extern "C" { - ULONG _tls_index__ = 0; - - IPC_CRTALLOC__(".tls$AAA") char _tls_start__ = 0; - IPC_CRTALLOC__(".tls$ZZZ") char _tls_end__ = 0; - - IPC_CRTALLOC__(".CRT$XLA") PIMAGE_TLS_CALLBACK _tls_xl_a__ = 0; - IPC_CRTALLOC__(".CRT$XLB") PIMAGE_TLS_CALLBACK _tls_xl_b__ = OnTlsCallback; - IPC_CRTALLOC__(".CRT$XLZ") PIMAGE_TLS_CALLBACK _tls_xl_z__ = 0; -} - -extern "C" NX_CRTALLOC_(".tls") const IMAGE_TLS_DIRECTORY _tls_used = { - (ULONG_PTR)(&_tls_start__ + 1), - (ULONG_PTR) &_tls_end__, - (ULONG_PTR) &_tls_index__, - (ULONG_PTR) &_tls_xl_b__, - (ULONG)0, (ULONG)0 -} - -#endif/*!MINGW*/ - -#endif/*_MSC_VER, __GNUC__*/ - -} // namespace tls -} // namespace ipc diff --git a/src/libipc/platform/tls_pointer_win.h b/src/libipc/platform/tls_pointer_win.h deleted file mode 100755 index 2e9e5a7..0000000 --- a/src/libipc/platform/tls_pointer_win.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include // std::atomic_thread_fence -#include // assert - -#include "libipc/tls_pointer.h" - -#include "libipc/platform/tls_detail_win.h" -#include "libipc/utility/utility.h" - -namespace ipc { -namespace tls { - -bool create(key_info * pkey, destructor_t destructor) { - assert(pkey != nullptr); - pkey->key_ = horrible_cast(destructor); - std::atomic_thread_fence(std::memory_order_seq_cst); - return true; -} - -void release(key_info const * pkey) { - assert(pkey != nullptr); - assert(tls_get_recs() != nullptr); - tls_get_recs()->erase(pkey); -} - -bool set(key_info const * pkey, void * ptr) { - assert(pkey != nullptr); - assert(tls_get_recs() != nullptr); - (*tls_get_recs())[pkey] = ptr; - return true; -} - -void * get(key_info const * pkey) { - assert(pkey != nullptr); - assert(tls_get_recs() != nullptr); - auto const recs = tls_get_recs(); - auto it = recs->find(pkey); - if (it == recs->end()) { - return nullptr; - } - return it->second; -} - -} // namespace tls -} // namespace ipc diff --git a/src/tls_pointer.cpp b/src/tls_pointer.cpp deleted file mode 100755 index dcfba88..0000000 --- a/src/tls_pointer.cpp +++ /dev/null @@ -1,8 +0,0 @@ - -#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ - defined(WINCE) || defined(_WIN32_WCE) -#include "libipc/platform/tls_pointer_win.h" -#else /*!WIN*/ -#include "libipc/platform/tls_pointer_linux.h" -#endif/*!WIN*/ diff --git a/test/test_thread_utility.cpp b/test/test_thread_utility.cpp index e0b0512..02dd0c2 100755 --- a/test/test_thread_utility.cpp +++ b/test/test_thread_utility.cpp @@ -11,7 +11,6 @@ #include "capo/type_name.hpp" #include "libipc/rw_lock.h" -#include "libipc/tls_pointer.h" #include "test.h" #include "thread_pool.h" @@ -89,6 +88,7 @@ void test_lock_performance(int w, int r) { // for (int i = 2; i <= ThreadMax; ++i) test_lock_performance(i, i); //} +#if 0 // disable ipc::tls TEST(Thread, tls_main_thread) { ipc::tls::pointer p; EXPECT_FALSE(p); @@ -199,4 +199,5 @@ TEST(Thread, tls_benchmark) { benchmark_tls("ipc_tls: int"); benchmark_tls("std_tls: Str"); benchmark_tls("ipc_tls: Str"); -} \ No newline at end of file +} +#endif \ No newline at end of file