96 lines
2.7 KiB
C++
96 lines
2.7 KiB
C++
/**
|
|
* @file : thread_local
|
|
* @created : Sunday Feb 04, 2024 18:33:04 CST
|
|
* @license : MIT
|
|
**/
|
|
|
|
#ifndef THREAD_LOCAL_H
|
|
#define THREAD_LOCAL_H
|
|
#include <cstddef>
|
|
#include <thread>
|
|
#include <type_traits>
|
|
|
|
namespace sled {
|
|
|
|
using ThreadId = std::thread::id;
|
|
using ThreadLocalKey = uint64_t;
|
|
|
|
namespace detail {
|
|
class ThreadLocalManager final {
|
|
public:
|
|
static ThreadLocalManager &Instance();
|
|
~ThreadLocalManager();
|
|
static ThreadId CurrentThreadId();
|
|
static ThreadLocalKey NextKey();
|
|
void *Get(const ThreadId &thread_id, const ThreadLocalKey &key) const;
|
|
void Delete(const ThreadId &thread_id, const ThreadLocalKey &key);
|
|
void Delete(const ThreadLocalKey &key);
|
|
void Set(const ThreadId &thread_id, const ThreadLocalKey &key, void *value);
|
|
|
|
private:
|
|
ThreadLocalManager();
|
|
class Impl;
|
|
std::unique_ptr<Impl> impl_;
|
|
};
|
|
}// namespace detail
|
|
|
|
template<typename T>
|
|
class ThreadLocal final {
|
|
public:
|
|
ThreadLocal() : key_(detail::ThreadLocalManager::NextKey()) {}
|
|
|
|
~ThreadLocal()
|
|
{ /*detail::ThreadLocalManager::Instance().Delete(key_); */
|
|
}
|
|
|
|
template<typename PointerT = T>
|
|
typename std::enable_if<std::is_pointer<PointerT>::value, PointerT>::type
|
|
Get() const
|
|
{
|
|
auto ptr = detail::ThreadLocalManager::Instance().Get(
|
|
detail::ThreadLocalManager::CurrentThreadId(), key_);
|
|
return static_cast<PointerT>(ptr);
|
|
}
|
|
|
|
template<typename IntT = T>
|
|
typename std::enable_if<std::is_integral<IntT>::value, IntT>::type
|
|
Get() const
|
|
{
|
|
static_assert(sizeof(IntT) <= sizeof(void *), "");
|
|
auto ptr = detail::ThreadLocalManager::Instance().Get(
|
|
detail::ThreadLocalManager::CurrentThreadId(), key_);
|
|
return static_cast<IntT>(static_cast<char *>(ptr)
|
|
- static_cast<char *>(0));
|
|
}
|
|
|
|
template<typename PointerT = T,
|
|
typename std::enable_if<
|
|
std::is_pointer<PointerT>::value
|
|
|| std::is_same<std::nullptr_t, PointerT>::value,
|
|
PointerT>::type = nullptr>
|
|
void Set(PointerT value)
|
|
{
|
|
detail::ThreadLocalManager::Instance().Set(
|
|
detail::ThreadLocalManager::CurrentThreadId(), key_,
|
|
static_cast<void *>(value));
|
|
}
|
|
|
|
template<typename IntT = T,
|
|
typename std::enable_if<std::is_integral<IntT>::value, IntT>::type
|
|
* = nullptr>
|
|
void Set(IntT value)
|
|
{
|
|
static_assert(sizeof(IntT) <= sizeof(void *), "");
|
|
detail::ThreadLocalManager::Instance().Set(
|
|
detail::ThreadLocalManager::CurrentThreadId(), key_,
|
|
(char *) 0 + value);
|
|
}
|
|
|
|
private:
|
|
const ThreadLocalKey key_;
|
|
};
|
|
|
|
}// namespace sled
|
|
|
|
#endif// THREAD_LOCAL_H
|