summaryrefslogtreecommitdiffstats
path: root/storage
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@yahooinc.com>2022-04-28 09:51:03 +0000
committerTor Brede Vekterli <vekterli@yahooinc.com>2022-04-28 09:51:03 +0000
commit2ec53d6f185a4a3e91ea6a2b879089eeac7896dd (patch)
tree6a883d788d1510235bf03be0be453bc9b74178c3 /storage
parent58a30c73a28e09beacdfc1fc34fcd63ebdcff8df (diff)
Make MinimumUsedBitsTracker thread safe for both reads and writes
Diffstat (limited to 'storage')
-rw-r--r--storage/src/vespa/storage/bucketdb/minimumusedbitstracker.h35
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);
}
};