ie_thread_local.hpp
Go to the documentation of this file.
1 // Copyright (C) 2018-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 
5 #pragma once
6 
7 /**
8  * @brief A file containing thread local class implementation.
9  * @file ie_thread_local.hpp
10  */
11 
12 #include "ie_parallel.hpp"
13 
14 #if IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO
15 # include <tbb/enumerable_thread_specific.h>
16 #else
17 # include <unordered_map>
18 # include <memory>
19 # include <thread>
20 # include <mutex>
21 # include <utility>
22 # include <functional>
23 #endif
24 
25 namespace InferenceEngine {
26 
27 #if IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO
28 
29 /**
30  * @brief A wrapper class to keep object to be thread local.
31  * @ingroup ie_dev_api_threading
32  * @tparam T A type of object to keep thread local.
33  */
34 template<typename T>
35 using ThreadLocal = tbb::enumerable_thread_specific<T>;
36 
37 #else
38 
39 template<typename T>
40 struct ThreadLocal {
41  using Map = std::unordered_map<std::thread::id, T>;
42  using Create = std::function<T()>;
43  Map _map;
44  mutable std::mutex _mutex;
45  Create _create;
46 
47  ThreadLocal() : _create{[]{return T{};}} {}
48  explicit ThreadLocal(const T& init) : _create{[init]{return init;}} {}
49  ThreadLocal(ThreadLocal&& other) :
50  _map{std::move(other._map)},
51  _create{std::move(other._create)} {
52  }
53  ThreadLocal& operator=(ThreadLocal&& other) {
54  _map = std::move(other._map);
55  _create = std::move(other._create);
56  return *this;
57  }
58  ThreadLocal(const ThreadLocal&) = delete;
59  ThreadLocal& operator=(const ThreadLocal&&) = delete;
60  explicit ThreadLocal(const Create& create_) : _create{create_}
61  {}
62 
63  T& local() {
64  auto threadId = std::this_thread::get_id();
65  std::lock_guard<std::mutex> lock{_mutex};
66  auto itThreadLocal = _map.find(threadId);
67  if (itThreadLocal != _map.end()) {
68  return itThreadLocal->second;
69  } else {
70  return _map.emplace(threadId, _create()).first->second;
71  }
72  }
73 
74  auto size() const -> decltype(_map.size()) {
75  std::lock_guard<std::mutex> lock{_mutex};
76  return _map.size();
77  }
78 
79  // WARNING: Thread Unsafe
80  template <typename It>
81  struct Iterator {
82  It it;
83  bool operator!=(const Iterator& other) {return it != other.it;}
84  Iterator& operator++() {++it; return *this;}
85  auto operator*() -> decltype(it->second) {return it->second;}
86  auto operator->() -> decltype(&(it->second)) {return &(it->second);}
87  auto operator*() const -> decltype(it->second) {return it->second;}
88  auto operator->() const -> decltype(&(it->second)) {return &(it->second);}
89  };
90 
91  auto begin() -> Iterator<decltype(_map.begin())> {return {_map.begin()};}
92  auto end() -> Iterator<decltype(_map.end())> {return {_map.end()};}
93  auto begin() const -> Iterator<decltype(_map.begin())> const {return {_map.begin()};}
94  auto end() const -> Iterator<decltype(_map.end())> const {return {_map.end()};}
95 };
96 
97 #endif
98 
99 } // namespace InferenceEngine
tbb::enumerable_thread_specific< T > ThreadLocal
A wrapper class to keep object to be thread local.
Definition: ie_thread_local.hpp:35
Inference Engine Plugin API namespace.