Toolbox snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
RefCount.hpp
Go to the documentation of this file.
1// The Reactive C++ Toolbox.
2// Copyright (C) 2013-2019 Swirly Cloud Limited
3// Copyright (C) 2022 Reactive Markets Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#ifndef TOOLBOX_UTIL_REFCOUNT_HPP
18#define TOOLBOX_UTIL_REFCOUNT_HPP
19
20#include <boost/intrusive_ptr.hpp>
21
22#include <atomic>
23
24namespace toolbox {
25inline namespace util {
26
28 using Type = std::atomic<int>;
29 static void acquire() noexcept { std::atomic_thread_fence(std::memory_order_acquire); }
30 static int fetch_add(Type& ref_count) noexcept
31 {
32 return ref_count.fetch_add(1, std::memory_order_relaxed);
33 }
34 static int fetch_sub(Type& ref_count) noexcept
35 {
36 return ref_count.fetch_sub(1, std::memory_order_release);
37 }
38 static int load(const Type& ref_count) noexcept
39 {
40 return ref_count.load(std::memory_order_relaxed);
41 }
42};
43
45 using Type = int;
46 static void acquire() noexcept {}
47 static int fetch_add(Type& ref_count) noexcept { return ref_count++; }
48#if defined(__GNUC__) && !defined(__clang__)
49#pragma GCC diagnostic push
50#pragma GCC diagnostic ignored "-Wuse-after-free"
51#endif
52 static int fetch_sub(Type& ref_count) noexcept { return ref_count--; }
53#if defined(__GNUC__) && !defined(__clang__)
54#pragma GCC diagnostic pop
55#endif
56 static int load(Type ref_count) noexcept { return ref_count; }
57};
58
60template <typename DerivedT, typename PolicyT>
61class RefCount {
62 public:
63 constexpr RefCount() noexcept = default;
65
66 // Copy.
69
70 // Move.
73
74 void add_ref() const noexcept { PolicyT::fetch_add(refs_); }
76 {
77 if (PolicyT::fetch_sub(refs_) == 1) {
78 PolicyT::acquire();
79 delete static_cast<const DerivedT*>(this);
80 }
81 }
82 int ref_count() const noexcept { return PolicyT::load(refs_); }
83
84 private:
85 mutable typename PolicyT::Type refs_{1};
86};
87
88template <typename DerivedT, typename PolicyT>
90{
91 ptr->add_ref();
92}
93
94template <typename DerivedT, typename PolicyT>
96{
97 ptr->release();
98}
99
100template <typename ValueT, typename... ArgsT>
101boost::intrusive_ptr<ValueT> make_intrusive(ArgsT&&... args)
102{
103 return {new ValueT{std::forward<ArgsT>(args)...}, false};
104}
105
106} // namespace util
107} // namespace toolbox
108
109#endif // TOOLBOX_UTIL_REFCOUNT_HPP
Base class for atomic referenced counted objects.
Definition RefCount.hpp:61
constexpr RefCount() noexcept=default
int ref_count() const noexcept
Definition RefCount.hpp:82
void add_ref() const noexcept
Definition RefCount.hpp:74
void release() const noexcept
Definition RefCount.hpp:75
void intrusive_ptr_release(const RefCount< DerivedT, PolicyT > *ptr) noexcept
Definition RefCount.hpp:95
boost::intrusive_ptr< ValueT > make_intrusive(ArgsT &&... args)
Definition RefCount.hpp:101
void intrusive_ptr_add_ref(const RefCount< DerivedT, PolicyT > *ptr) noexcept
Definition RefCount.hpp:89
constexpr auto bind() noexcept
Definition Slot.hpp:92
static int fetch_add(Type &ref_count) noexcept
Definition RefCount.hpp:30
static int fetch_sub(Type &ref_count) noexcept
Definition RefCount.hpp:34
static void acquire() noexcept
Definition RefCount.hpp:29
static int load(const Type &ref_count) noexcept
Definition RefCount.hpp:38
static int fetch_sub(Type &ref_count) noexcept
Definition RefCount.hpp:52
static int load(Type ref_count) noexcept
Definition RefCount.hpp:56
static void acquire() noexcept
Definition RefCount.hpp:46
static int fetch_add(Type &ref_count) noexcept
Definition RefCount.hpp:47