Coverage Report

Created: 2024-07-27 06:53

/src/rocksdb/util/atomic.h
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) Meta Platforms, Inc. and affiliates.
2
//  This source code is licensed under both the GPLv2 (found in the
3
//  COPYING file in the root directory) and Apache 2.0 License
4
//  (found in the LICENSE.Apache file in the root directory).
5
6
#pragma once
7
8
#include <atomic>
9
10
#include "rocksdb/rocksdb_namespace.h"
11
12
namespace ROCKSDB_NAMESPACE {
13
14
// Background:
15
// std::atomic is somewhat easy to misuse:
16
// * Implicit conversion to T using std::memory_order_seq_cst, along with
17
// memory order parameter defaults, make it easy to accidentally mix sequential
18
// consistency ordering with acquire/release memory ordering. See
19
// "The single total order might not be consistent with happens-before" at
20
// https://en.cppreference.com/w/cpp/atomic/memory_order
21
// * It's easy to use nonsensical (UB) combinations like store with
22
// std::memory_order_acquire.
23
// For such reasons, we provide wrappers below to make safe usage easier.
24
25
// Wrapper around std::atomic to avoid certain bugs (see Background above).
26
//
27
// This relaxed-only wrapper is intended for atomics that do not need
28
// ordering constraints with other data reads/writes aside from those
29
// necessary for computing data values or given by other happens-before
30
// relationships. For example, a cross-thread counter that never returns
31
// the same result can be a RelaxedAtomic.
32
template <typename T>
33
class RelaxedAtomic {
34
 public:
35
13.5k
  explicit RelaxedAtomic(T initial = {}) : v_(initial) {}
rocksdb::RelaxedAtomic<unsigned long>::RelaxedAtomic(unsigned long)
Line
Count
Source
35
9.02k
  explicit RelaxedAtomic(T initial = {}) : v_(initial) {}
rocksdb::RelaxedAtomic<unsigned int>::RelaxedAtomic(unsigned int)
Line
Count
Source
35
4.48k
  explicit RelaxedAtomic(T initial = {}) : v_(initial) {}
36
4.48k
  void StoreRelaxed(T desired) { v_.store(desired, std::memory_order_relaxed); }
rocksdb::RelaxedAtomic<unsigned int>::StoreRelaxed(unsigned int)
Line
Count
Source
36
4.48k
  void StoreRelaxed(T desired) { v_.store(desired, std::memory_order_relaxed); }
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned long>::StoreRelaxed(unsigned long)
37
4.48k
  T LoadRelaxed() const { return v_.load(std::memory_order_relaxed); }
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned long>::LoadRelaxed() const
rocksdb::RelaxedAtomic<unsigned int>::LoadRelaxed() const
Line
Count
Source
37
4.48k
  T LoadRelaxed() const { return v_.load(std::memory_order_relaxed); }
38
0
  bool CasWeakRelaxed(T& expected, T desired) {
39
0
    return v_.compare_exchange_weak(expected, desired,
40
0
                                    std::memory_order_relaxed);
41
0
  }
42
0
  bool CasStrongRelaxed(T& expected, T desired) {
43
0
    return v_.compare_exchange_strong(expected, desired,
44
0
                                      std::memory_order_relaxed);
45
0
  }
46
  T ExchangeRelaxed(T desired) {
47
    return v_.exchange(desired, std::memory_order_relaxed);
48
  }
49
0
  T FetchAddRelaxed(T operand) {
50
0
    return v_.fetch_add(operand, std::memory_order_relaxed);
51
0
  }
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned long>::FetchAddRelaxed(unsigned long)
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned int>::FetchAddRelaxed(unsigned int)
52
0
  T FetchSubRelaxed(T operand) {
53
0
    return v_.fetch_sub(operand, std::memory_order_relaxed);
54
0
  }
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned int>::FetchSubRelaxed(unsigned int)
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned long>::FetchSubRelaxed(unsigned long)
55
0
  T FetchAndRelaxed(T operand) {
56
0
    return v_.fetch_and(operand, std::memory_order_relaxed);
57
0
  }
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned long>::FetchAndRelaxed(unsigned long)
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned int>::FetchAndRelaxed(unsigned int)
58
0
  T FetchOrRelaxed(T operand) {
59
0
    return v_.fetch_or(operand, std::memory_order_relaxed);
60
0
  }
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned long>::FetchOrRelaxed(unsigned long)
Unexecuted instantiation: rocksdb::RelaxedAtomic<unsigned int>::FetchOrRelaxed(unsigned int)
61
  T FetchXorRelaxed(T operand) {
62
    return v_.fetch_xor(operand, std::memory_order_relaxed);
63
  }
64
65
 protected:
66
  std::atomic<T> v_;
67
};
68
69
// Wrapper around std::atomic to avoid certain bugs (see Background above).
70
//
71
// Except for some unusual cases requiring sequential consistency, this is
72
// a general-purpose atomic. Relaxed operations can be mixed in as appropriate.
73
template <typename T>
74
class AcqRelAtomic : public RelaxedAtomic<T> {
75
 public:
76
0
  explicit AcqRelAtomic(T initial = {}) : RelaxedAtomic<T>(initial) {}
77
0
  void Store(T desired) {
78
0
    RelaxedAtomic<T>::v_.store(desired, std::memory_order_release);
79
0
  }
80
0
  T Load() const {
81
0
    return RelaxedAtomic<T>::v_.load(std::memory_order_acquire);
82
0
  }
83
0
  bool CasWeak(T& expected, T desired) {
84
0
    return RelaxedAtomic<T>::v_.compare_exchange_weak(
85
0
        expected, desired, std::memory_order_acq_rel);
86
0
  }
87
0
  bool CasStrong(T& expected, T desired) {
88
0
    return RelaxedAtomic<T>::v_.compare_exchange_strong(
89
0
        expected, desired, std::memory_order_acq_rel);
90
0
  }
91
  T Exchange(T desired) {
92
    return RelaxedAtomic<T>::v_.exchange(desired, std::memory_order_acq_rel);
93
  }
94
0
  T FetchAdd(T operand) {
95
0
    return RelaxedAtomic<T>::v_.fetch_add(operand, std::memory_order_acq_rel);
96
0
  }
97
0
  T FetchSub(T operand) {
98
0
    return RelaxedAtomic<T>::v_.fetch_sub(operand, std::memory_order_acq_rel);
99
0
  }
100
0
  T FetchAnd(T operand) {
101
0
    return RelaxedAtomic<T>::v_.fetch_and(operand, std::memory_order_acq_rel);
102
0
  }
103
0
  T FetchOr(T operand) {
104
0
    return RelaxedAtomic<T>::v_.fetch_or(operand, std::memory_order_acq_rel);
105
0
  }
106
  T FetchXor(T operand) {
107
    return RelaxedAtomic<T>::v_.fetch_xor(operand, std::memory_order_acq_rel);
108
  }
109
};
110
111
}  // namespace ROCKSDB_NAMESPACE