diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-04-28 09:51:03 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-04-28 09:51:03 +0000 |
commit | 2ec53d6f185a4a3e91ea6a2b879089eeac7896dd (patch) | |
tree | 6a883d788d1510235bf03be0be453bc9b74178c3 /storage | |
parent | 58a30c73a28e09beacdfc1fc34fcd63ebdcff8df (diff) |
Make MinimumUsedBitsTracker thread safe for both reads and writes
Diffstat (limited to 'storage')
-rw-r--r-- | storage/src/vespa/storage/bucketdb/minimumusedbitstracker.h | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/storage/src/vespa/storage/bucketdb/minimumusedbitstracker.h b/storage/src/vespa/storage/bucketdb/minimumusedbitstracker.h index 881f7ed33cb..895446a31fe 100644 --- a/storage/src/vespa/storage/bucketdb/minimumusedbitstracker.h +++ b/storage/src/vespa/storage/bucketdb/minimumusedbitstracker.h @@ -1,8 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once -#include <algorithm> #include <vespa/document/bucket/bucketid.h> +#include <atomic> namespace storage { @@ -10,33 +10,42 @@ namespace storage { * Utility class for keeping track of the lowest used bits count seen * across a set of buckets. * - * Not threadsafe by itself. + * Thread safe for reads and writes. */ class MinimumUsedBitsTracker { - uint32_t _minUsedBits; + std::atomic<uint32_t> _min_used_bits; public: - MinimumUsedBitsTracker() - : _minUsedBits(58) + constexpr MinimumUsedBitsTracker() noexcept + : _min_used_bits(58) {} /** - * Returns true if new bucket led to a decrease in the used bits count. + * Returns true iff new bucket led to a decrease in the used bits count. */ - bool update(const document::BucketId& bucket) { - if (bucket.getUsedBits() < _minUsedBits) { - _minUsedBits = bucket.getUsedBits(); + bool update(const document::BucketId& bucket) noexcept { + const uint32_t bucket_bits = bucket.getUsedBits(); + uint32_t current_bits = _min_used_bits.load(std::memory_order_relaxed); + if (bucket_bits < current_bits) { + while (!_min_used_bits.compare_exchange_strong(current_bits, bucket_bits, + std::memory_order_relaxed, + std::memory_order_relaxed)) + { + if (bucket_bits >= current_bits) { + return false; // We've raced with another writer that had lower or equal bits to our own bucket. + } + } return true; } return false; } - uint32_t getMinUsedBits() const { - return _minUsedBits; + [[nodiscard]] uint32_t getMinUsedBits() const noexcept { + return _min_used_bits.load(std::memory_order_relaxed); } - void setMinUsedBits(uint32_t minUsedBits) { - _minUsedBits = minUsedBits; + void setMinUsedBits(uint32_t minUsedBits) noexcept { + _min_used_bits.store(minUsedBits, std::memory_order_relaxed); } }; |