#ifndef COMMON_THREAD_LOCAL_STORAGE_HPP
#define COMMON_THREAD_LOCAL_STORAGE_HPP
#include <assert.h>
#include <thread>
#include <utility>
#include <unordered_map>
#include "rw_mutex.hpp"
#include "z_magic.hpp"
namespace dnnl {
namespace impl {
namespace utils {
template <typename T>
struct thread_local_storage_t {
thread_local_storage_t() = default;
~thread_local_storage_t() = default;
DNNL_DISALLOW_COPY_AND_ASSIGN(thread_local_storage_t);
template <typename U>
T &set(U &&value) {
utils::lock_write_t lock_w(mutex_);
const auto tid = std::this_thread::get_id();
assert(storage_.count(tid) == 0);
auto it = storage_.emplace(tid, std::forward<U>(value));
assert(it.second);
return it.first->second;
}
bool is_set() {
utils::lock_read_t lock_r(mutex_);
return storage_.find(std::this_thread::get_id()) != storage_.end();
}
T &get() {
utils::lock_read_t lock_r(mutex_);
return storage_.at(std::this_thread::get_id());
}
template <typename U>
T &get(U &&def_value) {
{
utils::lock_read_t lock_r(mutex_);
auto it = storage_.find(std::this_thread::get_id());
if (it != storage_.end()) return it->second;
}
return set(std::forward<U>(def_value));
}
private:
std::unordered_map<std::thread::id, T> storage_;
utils::rw_mutex_t mutex_;
};
} } }
#endif