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