10 #ifndef EIGEN_CXX11_THREADPOOL_THREAD_LOCAL_H 11 #define EIGEN_CXX11_THREADPOOL_THREAD_LOCAL_H 13 #ifdef EIGEN_AVOID_THREAD_LOCAL 15 #ifdef EIGEN_THREAD_LOCAL 16 #undef EIGEN_THREAD_LOCAL 21 #if EIGEN_MAX_CPP_VER >= 11 && \ 22 ((EIGEN_COMP_GNUC && EIGEN_GNUC_AT_LEAST(4, 8)) || \ 23 __has_feature(cxx_thread_local) || \ 24 (EIGEN_COMP_MSVC >= 1900) ) 25 #define EIGEN_THREAD_LOCAL static thread_local 29 #if defined(__APPLE__) 32 #include <Availability.h> 33 #include <TargetConditionals.h> 37 #if defined(__apple_build_version__) && \ 38 ((__apple_build_version__ < 8000042) || \ 39 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)) 42 #undef EIGEN_THREAD_LOCAL 44 #elif defined(__ANDROID__) && EIGEN_COMP_CLANG 53 #if __has_include(<android/ndk-version.h>) 54 #include <android/ndk-version.h> 55 #endif // __has_include(<android/ndk-version.h>) 56 #if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \ 57 defined(__NDK_MINOR__) && \ 58 ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1))) 59 #undef EIGEN_THREAD_LOCAL 61 #endif // defined(__ANDROID__) && defined(__clang__) 63 #endif // EIGEN_AVOID_THREAD_LOCAL 112 template <
typename T,
118 "ThreadLocal data type must be default constructible");
123 internal::ThreadLocalNoOpRelease<
T>()) {}
127 internal::ThreadLocalNoOpRelease<
T>()) {}
130 : initialize_(
std::
move(initialize)),
137 data_.resize(capacity_);
138 for (
int i = 0;
i < capacity_; ++
i) {
139 ptr_.emplace_back(
nullptr);
145 if (capacity_ == 0)
return SpilledLocal(this_thread);
147 std::size_t h = std::hash<std::thread::id>()(this_thread);
148 const int start_idx = h % capacity_;
159 while (ptr_[idx].load() !=
nullptr) {
164 if (idx >= capacity_) idx -= capacity_;
165 if (idx == start_idx)
break;
172 if (filled_records_.load() >= capacity_)
return SpilledLocal(this_thread);
178 int insertion_index =
179 filled_records_.fetch_add(1, std::memory_order_relaxed);
180 if (insertion_index >= capacity_)
return SpilledLocal(this_thread);
184 data_[insertion_index].thread_id = this_thread;
185 initialize_(data_[insertion_index].
value);
197 const int insertion_idx = idx;
202 while (ptr_[idx].load() !=
nullptr) {
204 if (idx >= capacity_) idx -= capacity_;
211 }
while (!ptr_[idx].compare_exchange_weak(empty, inserted));
213 return inserted->
value;
220 for (
auto& ptr : ptr_) {
222 if (record ==
nullptr)
continue;
227 if (filled_records_.load(std::memory_order_relaxed) < capacity_)
return;
230 std::unique_lock<std::mutex> lock(mu_);
231 for (
auto& kv : per_thread_map_) {
232 f(kv.first, kv.second);
240 for (
auto& ptr : ptr_) {
242 if (record ==
nullptr)
continue;
243 release_(record->
value);
247 if (filled_records_.load(std::memory_order_relaxed) < capacity_)
return;
250 std::unique_lock<std::mutex> lock(mu_);
251 for (
auto& kv : per_thread_map_) {
264 std::unique_lock<std::mutex> lock(mu_);
266 auto it = per_thread_map_.find(this_thread);
267 if (it == per_thread_map_.end()) {
268 auto result = per_thread_map_.emplace(this_thread,
T());
270 initialize_((*
result.first).second);
271 return (*
result.first).second;
301 #endif // EIGEN_CXX11_THREADPOOL_THREAD_LOCAL_H std::thread::id thread_id
std::unordered_map< std::thread::id, T > per_thread_map_
Namespace containing all symbols from the Eigen library.
ThreadLocal(int capacity, Initialize initialize, Release release)
void ForEach(std::function< void(std::thread::id, T &)> f)
MaxSizeVector< std::atomic< ThreadIdAndValue * > > ptr_
static const Similarity3 id
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
MaxSizeVector< ThreadIdAndValue > data_
ThreadLocal(int capacity)
std::atomic< int > filled_records_
void operator()(T &) const
Eigen::Triplet< double > T
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
void operator()(T &) const
T & SpilledLocal(std::thread::id this_thread)
ThreadLocal(int capacity, Initialize initialize)
Values initialize(const NonlinearFactorGraph &graph, bool useOdometricPath)