| #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 |