#include "ThreadLocalPtr.h" #include namespace caffe2 { // meyer's singleton AllThreadLocalHelperVector* getAllThreadLocalHelperVector() { // leak the pointer to avoid dealing with destruction order issues static auto* instance = new AllThreadLocalHelperVector(); return instance; } ThreadLocalHelper* getThreadLocalHelper() { static thread_local ThreadLocalHelper instance; return &instance; } // AllThreadLocalHelperVector void AllThreadLocalHelperVector::push_back(ThreadLocalHelper* helper) { std::lock_guard lg(mutex_); vector_.push_back(helper); } void AllThreadLocalHelperVector::erase(ThreadLocalHelper* helper) { std::lock_guard lg(mutex_); vector_.erase( std::remove(vector_.begin(), vector_.end(), helper), vector_.end()); } void AllThreadLocalHelperVector::erase_tlp(ThreadLocalPtrImpl* ptr) { std::lock_guard lg(mutex_); for (auto* ins : vector_) { ins->erase(ptr); } } // ThreadLocalHelper ThreadLocalHelper::ThreadLocalHelper() { getAllThreadLocalHelperVector()->push_back(this); } ThreadLocalHelper::~ThreadLocalHelper() { getAllThreadLocalHelperVector()->erase(this); } void ThreadLocalHelper::insert( ThreadLocalPtrImpl* tl_ptr, std::shared_ptr ptr) { std::lock_guard lg(mutex_); mapping_.insert(std::make_pair(tl_ptr, std::move(ptr))); } void* ThreadLocalHelper::get(ThreadLocalPtrImpl* key) { /* Grabbing the mutex for the thread local map protecting the case * when other object exits(~ThreadLocalPtrImpl()), and removes the * element in the map, which will change the iterator returned * by find. */ std::lock_guard lg(mutex_); auto it = mapping_.find(key); if (it == mapping_.end()) { return nullptr; } else { return it->second.get(); } } void ThreadLocalHelper::erase(ThreadLocalPtrImpl* key) { std::lock_guard lg(mutex_); mapping_.erase(key); } ThreadLocalPtrImpl::~ThreadLocalPtrImpl() { getAllThreadLocalHelperVector()->erase_tlp(this); } } // namespace caffe2