WARN: It's not thread safe to call it concurrently with `local()`.
| 214 | |
| 215 | // WARN: It's not thread safe to call it concurrently with `local()`. |
| 216 | void ForEach(std::function<void(std::thread::id, T&)> f) { |
| 217 | // Reading directly from `data_` is unsafe, because only CAS to the |
| 218 | // record in `ptr_` makes all changes visible to other threads. |
| 219 | for (auto& ptr : ptr_) { |
| 220 | ThreadIdAndValue* record = ptr.load(); |
| 221 | if (record == nullptr) continue; |
| 222 | f(record->thread_id, record->value); |
| 223 | } |
| 224 | |
| 225 | // We did not spill into the map based storage. |
| 226 | if (filled_records_.load(std::memory_order_relaxed) < capacity_) return; |
| 227 | |
| 228 | // Adds a happens before edge from the last call to SpilledLocal(). |
| 229 | EIGEN_MUTEX_LOCK lock(mu_); |
| 230 | for (auto& kv : per_thread_map_) { |
| 231 | f(kv.first, kv.second); |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | // WARN: It's not thread safe to call it concurrently with `local()`. |
| 236 | ~ThreadLocal() { |