ReactivePlusPlus
ReactiveX implementation for C++20
Loading...
Searching...
No Matches
refcount_disposable.hpp
1// ReactivePlusPlus library
2//
3// Copyright Aleksey Loginov 2023 - present.
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// https://www.boost.org/LICENSE_1_0.txt)
7//
8// Project home: https://github.com/victimsnino/ReactivePlusPlus
9//
10
11#pragma once
12
13#include <rpp/disposables/fwd.hpp>
14
15#include <rpp/disposables/composite_disposable.hpp>
16#include <rpp/disposables/details/base_disposable.hpp>
17#include <rpp/disposables/disposable_wrapper.hpp>
18
19#include <atomic>
20#include <limits>
21
22namespace rpp::details
23{
24 class refocunt_disposable_inner;
25} // namespace rpp::details
26
27namespace rpp
28{
31 {
32
33 void release()
34 {
35 auto current_value = m_refcount.load(std::memory_order::seq_cst);
36 while (current_value != s_disposed)
37 {
38 const size_t new_value = current_value == 1 ? s_disposed : current_value - 1;
39 if (!m_refcount.compare_exchange_strong(current_value, new_value, std::memory_order::seq_cst))
40 continue;
41
42 if (new_value == s_disposed)
43 dispose();
44 return;
45 }
46 }
47
48 void composite_dispose_impl(interface_disposable::Mode) noexcept override
49 {
50 m_refcount.store(s_disposed, std::memory_order::seq_cst);
51 }
52
53 public:
55 refcount_disposable() = default;
56
58
59 private:
60 std::atomic<size_t> m_refcount{0};
61 constexpr static size_t s_disposed = std::numeric_limits<size_t>::max();
62 };
63} // namespace rpp
64
65namespace rpp::details
66{
68 , public rpp::details::enable_wrapper_from_this<refocunt_disposable_inner>
69 {
70 public:
72 : m_state{std::move(state)}
73 {
74 }
75
76 void composite_dispose_impl(interface_disposable::Mode mode) noexcept override
77 {
78 if (mode != interface_disposable::Mode::Destroying)
79 m_state.remove(this->wrapper_from_this());
80
81 if (const auto locked = m_state.lock())
82 locked->release();
84 }
85
86 private:
88 };
89
90} // namespace rpp::details
91
92namespace rpp
93{
94 inline composite_disposable_wrapper refcount_disposable::add_ref()
95 {
96 auto current_value = m_refcount.load(std::memory_order::seq_cst);
97 while (true)
98 {
99 if (current_value == s_disposed)
101
102 // just need atomicity, not guarding anything
103 if (m_refcount.compare_exchange_strong(current_value, current_value + 1, std::memory_order::seq_cst))
104 {
106 add(inner.as_weak());
107 return inner;
108 }
109 }
110 }
111} // namespace rpp
Disposable which can keep some other sub-disposables. When this root disposable is disposed,...
Definition composite_disposable.hpp:175
Definition disposable_wrapper.hpp:252
Definition refcount_disposable.hpp:69
static disposable_wrapper_impl make(TArgs &&... args)
Definition disposable_wrapper.hpp:164
static disposable_wrapper_impl empty()
Creates disposable_wrapper which behaves like disposed disposable.
Definition disposable_wrapper.hpp:178
Definition refcount_disposable.hpp:31
void dispose() noexcept
Dispose disposable and free any underlying resources and etc.
Definition interface_disposable.hpp:36