proxygen
CoreCachedSharedPtr.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <array>
20 #include <memory>
21 
26 
27 namespace folly {
28 
39 template <class T, size_t kNumSlots = 64>
41  public:
42  explicit CoreCachedSharedPtr(const std::shared_ptr<T>& p = nullptr) {
43  reset(p);
44  }
45 
46  void reset(const std::shared_ptr<T>& p = nullptr) {
47  // Allocate each Holder in a different CoreRawAllocator stripe to
48  // prevent false sharing. Their control blocks will be adjacent
49  // thanks to allocate_shared().
50  for (auto slot : folly::enumerate(slots_)) {
51  auto alloc = getCoreAllocator<Holder, kNumSlots>(slot.index);
52  auto holder = std::allocate_shared<Holder>(alloc, p);
53  *slot = std::shared_ptr<T>(holder, p.get());
54  }
55  }
56 
57  std::shared_ptr<T> get() const {
58  return slots_[AccessSpreader<>::current(kNumSlots)];
59  }
60 
61  private:
62  using Holder = std::shared_ptr<T>;
63 
64  template <class, size_t>
65  friend class CoreCachedWeakPtr;
66 
67  std::array<std::shared_ptr<T>, kNumSlots> slots_;
68 };
69 
70 template <class T, size_t kNumSlots = 64>
72  public:
74  for (auto slot : folly::enumerate(slots_)) {
75  *slot = p.slots_[slot.index];
76  }
77  }
78 
79  std::weak_ptr<T> get() const {
80  return slots_[AccessSpreader<>::current(kNumSlots)];
81  }
82 
83  private:
84  std::array<std::weak_ptr<T>, kNumSlots> slots_;
85 };
86 
99 template <class T, size_t kNumSlots = 64>
101  public:
102  explicit AtomicCoreCachedSharedPtr(const std::shared_ptr<T>& p = nullptr) {
103  reset(p);
104  }
105 
107  auto slots = slots_.load(std::memory_order_acquire);
108  // Delete of AtomicCoreCachedSharedPtr must be synchronized, no
109  // need for stlots->retire().
110  if (slots) {
111  delete slots;
112  }
113  }
114 
115  void reset(const std::shared_ptr<T>& p = nullptr) {
116  auto newslots = folly::make_unique<Slots>();
117  // Allocate each Holder in a different CoreRawAllocator stripe to
118  // prevent false sharing. Their control blocks will be adjacent
119  // thanks to allocate_shared().
120  for (auto slot : folly::enumerate(newslots->slots_)) {
121  auto alloc = getCoreAllocator<Holder, kNumSlots>(slot.index);
122  auto holder = std::allocate_shared<Holder>(alloc, p);
123  *slot = std::shared_ptr<T>(holder, p.get());
124  }
125 
126  auto oldslots = slots_.exchange(newslots.release());
127  if (oldslots) {
128  oldslots->retire();
129  }
130  }
131 
132  std::shared_ptr<T> get() const {
133  folly::hazptr_local<1> hazptr;
134  auto slots = hazptr[0].get_protected(slots_);
135  if (!slots) {
136  return nullptr;
137  }
138  return (slots->slots_)[AccessSpreader<>::current(kNumSlots)];
139  }
140 
141  private:
142  using Holder = std::shared_ptr<T>;
143  struct Slots : folly::hazptr_obj_base<Slots> {
144  std::array<std::shared_ptr<T>, kNumSlots> slots_;
145  };
146  std::atomic<Slots*> slots_{nullptr};
147 };
148 
149 } // namespace folly
std::array< std::weak_ptr< T >, kNumSlots > slots_
void reset(const std::shared_ptr< T > &p=nullptr)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
AtomicCoreCachedSharedPtr(const std::shared_ptr< T > &p=nullptr)
void reset(const std::shared_ptr< T > &p=nullptr)
std::array< std::shared_ptr< T >, kNumSlots > slots_
detail::RangeEnumerator< Range > enumerate(Range &&r)
Definition: Enumerate.h:167
std::shared_ptr< T > Holder
static size_t current(size_t numStripes)
CoreCachedWeakPtr(const CoreCachedSharedPtr< T, kNumSlots > &p)
std::array< std::shared_ptr< T >, kNumSlots > slots_
CoreCachedSharedPtr(const std::shared_ptr< T > &p=nullptr)