]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/util/core_local.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rocksdb / util / core_local.h
1 // Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
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 <cstddef>
9 #include <thread>
10 #include <utility>
11 #include <vector>
12
13 #include "port/likely.h"
14 #include "port/port.h"
15 #include "util/random.h"
16
17 namespace rocksdb {
18
19 // An array of core-local values. Ideally the value type, T, is cache aligned to
20 // prevent false sharing.
21 template <typename T>
22 class CoreLocalArray {
23 public:
24 CoreLocalArray();
25
26 size_t Size() const;
27 // returns pointer to the element corresponding to the core that the thread
28 // currently runs on.
29 T* Access() const;
30 // same as above, but also returns the core index, which the client can cache
31 // to reduce how often core ID needs to be retrieved. Only do this if some
32 // inaccuracy is tolerable, as the thread may migrate to a different core.
33 std::pair<T*, size_t> AccessElementAndIndex() const;
34 // returns pointer to element for the specified core index. This can be used,
35 // e.g., for aggregation, or if the client caches core index.
36 T* AccessAtCore(size_t core_idx) const;
37
38 private:
39 std::unique_ptr<T[]> data_;
40 int size_shift_;
41 };
42
43 template <typename T>
44 CoreLocalArray<T>::CoreLocalArray() {
45 int num_cpus = static_cast<int>(std::thread::hardware_concurrency());
46 // find a power of two >= num_cpus and >= 8
47 size_shift_ = 3;
48 while (1 << size_shift_ < num_cpus) {
49 ++size_shift_;
50 }
51 data_.reset(new T[static_cast<size_t>(1) << size_shift_]);
52 }
53
54 template <typename T>
55 size_t CoreLocalArray<T>::Size() const {
56 return static_cast<size_t>(1) << size_shift_;
57 }
58
59 template <typename T>
60 T* CoreLocalArray<T>::Access() const {
61 return AccessElementAndIndex().first;
62 }
63
64 template <typename T>
65 std::pair<T*, size_t> CoreLocalArray<T>::AccessElementAndIndex() const {
66 int cpuid = port::PhysicalCoreID();
67 size_t core_idx;
68 if (UNLIKELY(cpuid < 0)) {
69 // cpu id unavailable, just pick randomly
70 core_idx = Random::GetTLSInstance()->Uniform(1 << size_shift_);
71 } else {
72 core_idx = static_cast<size_t>(cpuid & ((1 << size_shift_) - 1));
73 }
74 return {AccessAtCore(core_idx), core_idx};
75 }
76
77 template <typename T>
78 T* CoreLocalArray<T>::AccessAtCore(size_t core_idx) const {
79 assert(core_idx < static_cast<size_t>(1) << size_shift_);
80 return &data_[core_idx];
81 }
82
83 } // namespace rocksdb