1 | /* |
2 | * Copyright 2018-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 | |
18 | #include <folly/synchronization/Hazptr-fwd.h> |
19 | |
20 | #include <folly/concurrency/CacheLocality.h> |
21 | |
22 | #include <atomic> |
23 | |
24 | namespace folly { |
25 | |
26 | /** |
27 | * hazptr_rec: |
28 | * |
29 | * Contains the actual hazard pointer. |
30 | */ |
31 | template <template <typename> class Atom> |
32 | class alignas(hardware_destructive_interference_size) hazptr_rec { |
33 | Atom<const void*> hazptr_{nullptr}; // the hazard pointer |
34 | hazptr_domain<Atom>* domain_; |
35 | hazptr_rec* next_; |
36 | Atom<bool> active_{false}; |
37 | |
38 | friend class hazptr_domain<Atom>; |
39 | friend class hazptr_holder<Atom>; |
40 | friend class hazptr_tc_entry<Atom>; |
41 | |
42 | const void* hazptr() const noexcept { |
43 | return hazptr_.load(std::memory_order_acquire); |
44 | } |
45 | |
46 | FOLLY_ALWAYS_INLINE void reset_hazptr(const void* p = nullptr) noexcept { |
47 | hazptr_.store(p, std::memory_order_release); |
48 | } |
49 | |
50 | bool active() const noexcept { |
51 | return active_.load(std::memory_order_acquire); |
52 | } |
53 | |
54 | void set_active() noexcept { |
55 | active_.store(true, std::memory_order_relaxed); |
56 | } |
57 | |
58 | bool try_acquire() noexcept { |
59 | bool a = active(); |
60 | return !a && |
61 | active_.compare_exchange_strong( |
62 | a, true, std::memory_order_release, std::memory_order_relaxed); |
63 | } |
64 | |
65 | void release() noexcept { |
66 | active_.store(false, std::memory_order_release); |
67 | } |
68 | |
69 | hazptr_rec<Atom>* next() { |
70 | return next_; |
71 | } |
72 | |
73 | void set_next(hazptr_rec<Atom>* rec) { |
74 | next_ = rec; |
75 | } |
76 | |
77 | FOLLY_ALWAYS_INLINE hazptr_domain<Atom>* domain() { |
78 | return domain_; |
79 | } |
80 | |
81 | void set_domain(hazptr_domain<Atom>* dom) { |
82 | domain_ = dom; |
83 | } |
84 | }; // hazptr_rec |
85 | |
86 | } // namespace folly |
87 | |