| #include "ThreadLocalPtr.h" | |
| #include <algorithm> | |
| 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<std::mutex> lg(mutex_); | |
| vector_.push_back(helper); | |
| } | |
| void AllThreadLocalHelperVector::erase(ThreadLocalHelper* helper) { | |
| std::lock_guard<std::mutex> lg(mutex_); | |
| vector_.erase( | |
| std::remove(vector_.begin(), vector_.end(), helper), vector_.end()); | |
| } | |
| void AllThreadLocalHelperVector::erase_tlp(ThreadLocalPtrImpl* ptr) { | |
| std::lock_guard<std::mutex> 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<void> ptr) { | |
| std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> lg(mutex_); | |
| mapping_.erase(key); | |
| } | |
| ThreadLocalPtrImpl::~ThreadLocalPtrImpl() { | |
| getAllThreadLocalHelperVector()->erase_tlp(this); | |
| } | |
| } // namespace caffe2 |