#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