/ Shared locking
| 249 | // Shared locking |
| 250 | // |
| 251 | void |
| 252 | lock_shared(Token &token) |
| 253 | { |
| 254 | debug_assert(SLOT_SIZE >= DenseThreadId::num_possible_values()); |
| 255 | |
| 256 | // Fast path |
| 257 | if (_mutex.read_bias.load(std::memory_order_acquire)) { |
| 258 | size_t index = DenseThreadId::self() % SLOT_SIZE; |
| 259 | Slot &slot = _mutex.readers[index]; |
| 260 | bool expect = false; |
| 261 | if (slot.mu.compare_exchange_strong(expect, true, std::memory_order_relaxed)) { |
| 262 | // recheck |
| 263 | if (_mutex.read_bias.load(std::memory_order_acquire)) { |
| 264 | token = index + 1; |
| 265 | return; |
| 266 | } else { |
| 267 | slot.mu.store(false, std::memory_order_relaxed); |
| 268 | } |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | // Slow path |
| 273 | _mutex.underlying.lock_shared(); |
| 274 | if (_mutex.read_bias.load(std::memory_order_acquire) == false && _now() >= _mutex.inhibit_until) { |
| 275 | _mutex.read_bias.store(true, std::memory_order_release); |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | bool |
| 280 | try_lock_shared(Token &token) |
no test coverage detected