proxygen
HazptrSWMRSet.h
Go to the documentation of this file.
1 /*
2  * Copyright 2016-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 #pragma once
17 
19 
20 #include <atomic>
21 
22 namespace folly {
23 
30 template <typename T, template <typename> class Atom = std::atomic>
32  template <typename Node>
33  struct Reclaimer {
34  void operator()(Node* p) {
35  delete p;
36  }
37  };
38 
39  struct Node : public hazptr_obj_base<Node, Atom, Reclaimer<Node>> {
41  Atom<Node*> next_;
42 
43  Node(T e, Node* n) : elem_(e), next_(n) {}
44  };
45 
46  Atom<Node*> head_{nullptr};
47 
48  public:
50 
52  auto p = head_.load();
53  while (p) {
54  auto next = p->next_.load();
55  delete p;
56  p = next;
57  }
58  }
59 
60  bool add(T v) {
61  auto prev = &head_;
62  locate_lower_bound(v, prev);
63  auto curr = prev->load(std::memory_order_relaxed);
64  if (curr && curr->elem_ == v) {
65  return false;
66  }
67  prev->store(new Node(std::move(v), curr));
68  return true;
69  }
70 
71  bool remove(const T& v) {
72  auto prev = &head_;
73  locate_lower_bound(v, prev);
74  auto curr = prev->load(std::memory_order_relaxed);
75  if (!curr || curr->elem_ != v) {
76  return false;
77  }
78  Node* curr_next = curr->next_.load();
79  // Patch up the actual list...
80  prev->store(curr_next, std::memory_order_release);
81  // ...and only then null out the removed node.
82  curr->next_.store(nullptr, std::memory_order_release);
83  curr->retire();
84  return true;
85  }
86 
87  /* Used by readers */
88  bool contains(const T& val) const {
89  /* Two hazard pointers for hand-over-hand traversal. */
91  hazptr_holder<Atom>* hptr_prev = &hptr[0];
92  hazptr_holder<Atom>* hptr_curr = &hptr[1];
93  while (true) {
94  auto prev = &head_;
95  auto curr = prev->load(std::memory_order_acquire);
96  while (true) {
97  if (!curr) {
98  return false;
99  }
100  if (!hptr_curr->try_protect(curr, *prev)) {
101  break;
102  }
103  auto next = curr->next_.load(std::memory_order_acquire);
104  if (prev->load(std::memory_order_acquire) != curr) {
105  break;
106  }
107  if (curr->elem_ == val) {
108  return true;
109  } else if (!(curr->elem_ < val)) {
110  return false; // because the list is sorted
111  }
112  prev = &(curr->next_);
113  curr = next;
114  std::swap(hptr_curr, hptr_prev);
115  }
116  }
117  }
118 
119  private:
120  /* Used by the single writer */
121  void locate_lower_bound(const T& v, Atom<Node*>*& prev) const {
122  auto curr = prev->load(std::memory_order_relaxed);
123  while (curr) {
124  if (curr->elem_ >= v) {
125  break;
126  }
127  prev = &(curr->next_);
128  curr = curr->next_.load(std::memory_order_relaxed);
129  }
130  return;
131  }
132 };
133 
134 } // namespace folly
auto v
FOLLY_ALWAYS_INLINE bool try_protect(T *&ptr, const Atom< T * > &src) noexcept
Definition: HazptrHolder.h:116
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
double val
Definition: String.cpp:273
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
#define nullptr
Definition: http_parser.c:41
#define Atom
bool contains(const T &val) const
Definition: HazptrSWMRSet.h:88
Atom< Node * > head_
Definition: HazptrSWMRSet.h:46
void locate_lower_bound(const T &v, Atom< Node * > *&prev) const
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
def next(obj)
Definition: ast.py:58