mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
commit
130e4d61a6
2
.github/workflows/c-cpp.yml
vendored
2
.github/workflows/c-cpp.yml
vendored
@ -2,7 +2,7 @@ name: C/C++ CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master, develop ]
|
branches: [ master, develop, issue-* ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master, develop ]
|
branches: [ master, develop ]
|
||||||
|
|
||||||
|
|||||||
@ -44,9 +44,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef IPC_EXPORT
|
#ifndef IPC_EXPORT
|
||||||
#if defined(__IPC_LIBRARY__)
|
#if defined(LIBIPC_LIBRARY_SHARED_BUILDING__)
|
||||||
# define IPC_EXPORT IPC_DECL_EXPORT
|
# define IPC_EXPORT IPC_DECL_EXPORT
|
||||||
#else
|
#elif defined(LIBIPC_LIBRARY_SHARED_USING__)
|
||||||
# define IPC_EXPORT IPC_DECL_IMPORT
|
# define IPC_EXPORT IPC_DECL_IMPORT
|
||||||
|
#else
|
||||||
|
# define IPC_EXPORT
|
||||||
#endif
|
#endif
|
||||||
#endif /*IPC_EXPORT*/
|
#endif /*IPC_EXPORT*/
|
||||||
|
|||||||
@ -1,112 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory> // std::unique_ptr
|
|
||||||
#include <utility> // std::forward
|
|
||||||
#include <cstddef> // 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<int> 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<int> p;
|
|
||||||
* p.create_once(123);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class pointer : public key_info {
|
|
||||||
|
|
||||||
pointer(pointer const &) = delete;
|
|
||||||
pointer & operator=(pointer const &) = delete;
|
|
||||||
|
|
||||||
void destruct() const {
|
|
||||||
delete static_cast<T*>(tls::get(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
|
|
||||||
pointer() {
|
|
||||||
tls::create(this, [](void* p) {
|
|
||||||
delete static_cast<T*>(p);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
~pointer() {
|
|
||||||
destruct();
|
|
||||||
tls::release(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... P>
|
|
||||||
T* create(P&&... params) {
|
|
||||||
destruct();
|
|
||||||
std::unique_ptr<T> ptr { new T(std::forward<P>(params)...) };
|
|
||||||
if (!tls::set(this, ptr.get())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return ptr.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... P>
|
|
||||||
T* create_once(P&&... params) {
|
|
||||||
auto p = static_cast<T*>(tls::get(this));
|
|
||||||
if (p == nullptr) {
|
|
||||||
std::unique_ptr<T> ptr { new T(std::forward<P>(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<T *>(tls::get(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const {
|
|
||||||
return tls::get(this) != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
T & operator* () { return *static_cast<T *>(*this); }
|
|
||||||
const T & operator* () const { return *static_cast<T *>(*this); }
|
|
||||||
|
|
||||||
T * operator->() { return static_cast<T *>(*this); }
|
|
||||||
const T * operator->() const { return static_cast<T *>(*this); }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace tls
|
|
||||||
} // namespace ipc
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
project(ipc)
|
project(ipc)
|
||||||
|
|
||||||
add_compile_options(-D__IPC_LIBRARY__)
|
option(LIBIPC_BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
add_compile_options(-fPIC)
|
add_compile_options(-fPIC)
|
||||||
@ -26,7 +26,17 @@ file(GLOB HEAD_FILES
|
|||||||
${LIBIPC_PROJECT_DIR}/src/libipc/platform/*.h
|
${LIBIPC_PROJECT_DIR}/src/libipc/platform/*.h
|
||||||
${LIBIPC_PROJECT_DIR}/src/libipc/utility/*.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)
|
if(NOT MSVC)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||||
pthread
|
pthread
|
||||||
|
|||||||
17
src/ipc.cpp
17
src/ipc.cpp
@ -13,7 +13,6 @@
|
|||||||
#include "libipc/ipc.h"
|
#include "libipc/ipc.h"
|
||||||
#include "libipc/def.h"
|
#include "libipc/def.h"
|
||||||
#include "libipc/shm.h"
|
#include "libipc/shm.h"
|
||||||
#include "libipc/tls_pointer.h"
|
|
||||||
#include "libipc/pool_alloc.h"
|
#include "libipc/pool_alloc.h"
|
||||||
#include "libipc/queue.h"
|
#include "libipc/queue.h"
|
||||||
#include "libipc/policy.h"
|
#include "libipc/policy.h"
|
||||||
@ -253,19 +252,6 @@ struct conn_info_head {
|
|||||||
ipc::waiter cc_waiter_, wt_waiter_, rd_waiter_;
|
ipc::waiter cc_waiter_, wt_waiter_, rd_waiter_;
|
||||||
ipc::shm::handle acc_h_;
|
ipc::shm::handle acc_h_;
|
||||||
|
|
||||||
/*
|
|
||||||
* <Remarks> thread_local may have some bugs.
|
|
||||||
*
|
|
||||||
* <Reference>
|
|
||||||
* - 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<ipc::unordered_map<msg_id_t, cache_t>> recv_cache_;
|
|
||||||
|
|
||||||
conn_info_head(char const * name)
|
conn_info_head(char const * name)
|
||||||
: name_ {name}
|
: name_ {name}
|
||||||
, cc_id_ {(cc_acc() == nullptr) ? 0 : cc_acc()->fetch_add(1, std::memory_order_relaxed)}
|
, 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() {
|
auto& recv_cache() {
|
||||||
return *recv_cache_.create_once();
|
thread_local ipc::unordered_map<msg_id_t, cache_t> tls;
|
||||||
|
return tls;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include "libipc/def.h"
|
#include "libipc/def.h"
|
||||||
#include "libipc/rw_lock.h"
|
#include "libipc/rw_lock.h"
|
||||||
#include "libipc/tls_pointer.h"
|
|
||||||
#include "libipc/pool_alloc.h"
|
#include "libipc/pool_alloc.h"
|
||||||
|
|
||||||
#include "libipc/utility/concept.h"
|
#include "libipc/utility/concept.h"
|
||||||
@ -155,18 +154,16 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
friend class alloc_proxy;
|
friend class alloc_proxy;
|
||||||
|
|
||||||
using ref_t = alloc_proxy&;
|
using ref_t = alloc_proxy&;
|
||||||
using tls_t = tls::pointer<alloc_proxy>;
|
|
||||||
|
|
||||||
tls_t tls_;
|
|
||||||
std::function<ref_t()> get_alloc_;
|
std::function<ref_t()> get_alloc_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename ... P>
|
template <typename ... P>
|
||||||
async_wrapper(P ... pars) {
|
async_wrapper(P ... pars) {
|
||||||
get_alloc_ = [this, pars ...]()->ref_t {
|
get_alloc_ = [this, pars ...]()->ref_t {
|
||||||
return *tls_.create_once(this, pars ...);
|
thread_local alloc_proxy tls(pars ...);
|
||||||
|
return tls;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <unordered_map> // std::unordered_map
|
|
||||||
#include <cassert> // 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<destructor_t>(pkey->key_);
|
|
||||||
if (destructor != nullptr) destructor(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct tls_recs : public std::unordered_map<key_info const *, void *> {
|
|
||||||
~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
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
|
|
||||||
#include <pthread.h> // pthread_...
|
|
||||||
|
|
||||||
#include <atomic> // std::atomic_thread_fence
|
|
||||||
#include <cassert> // 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<key_t>(k);
|
|
||||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void release(key_info const * pkey) {
|
|
||||||
assert(pkey != nullptr);
|
|
||||||
static_cast<void>(
|
|
||||||
native::release(horrible_cast<native::key_t>(pkey->key_)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool set(key_info const * pkey, void* ptr) {
|
|
||||||
assert(pkey != nullptr);
|
|
||||||
return native::set(horrible_cast<native::key_t>(pkey->key_), ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void * get(key_info const * pkey) {
|
|
||||||
assert(pkey != nullptr);
|
|
||||||
return native::get(horrible_cast<native::key_t>(pkey->key_));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace tls
|
|
||||||
} // namespace ipc
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#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
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <atomic> // std::atomic_thread_fence
|
|
||||||
#include <cassert> // 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<key_t>(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
|
|
||||||
@ -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*/
|
|
||||||
@ -11,7 +11,6 @@
|
|||||||
#include "capo/type_name.hpp"
|
#include "capo/type_name.hpp"
|
||||||
|
|
||||||
#include "libipc/rw_lock.h"
|
#include "libipc/rw_lock.h"
|
||||||
#include "libipc/tls_pointer.h"
|
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "thread_pool.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);
|
// for (int i = 2; i <= ThreadMax; ++i) test_lock_performance(i, i);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
#if 0 // disable ipc::tls
|
||||||
TEST(Thread, tls_main_thread) {
|
TEST(Thread, tls_main_thread) {
|
||||||
ipc::tls::pointer<int> p;
|
ipc::tls::pointer<int> p;
|
||||||
EXPECT_FALSE(p);
|
EXPECT_FALSE(p);
|
||||||
@ -200,3 +200,4 @@ TEST(Thread, tls_benchmark) {
|
|||||||
benchmark_tls<std_tls, Str>("std_tls: Str");
|
benchmark_tls<std_tls, Str>("std_tls: Str");
|
||||||
benchmark_tls<ipc_tls, Str>("ipc_tls: Str");
|
benchmark_tls<ipc_tls, Str>("ipc_tls: Str");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
Loading…
x
Reference in New Issue
Block a user