Skip to content

Commit 7f00758

Browse files
falucoAlaiaL
authored andcommitted
support: shrink the size of the stop_event_token class by half to make it easier to use in lambda captures of unique_task
1 parent 66b0932 commit 7f00758

File tree

1 file changed

+86
-95
lines changed

1 file changed

+86
-95
lines changed

include/srsran/support/synchronization/stop_event.h

Lines changed: 86 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -17,100 +17,7 @@
1717

1818
namespace srsran {
1919

20-
/// \brief Observer of calls to stop() on the associated stop_event_source.
21-
///
22-
/// When it gets reset or destroyed, it notifies the stop_event_source that one observer is gone.
23-
class stop_event_token
24-
{
25-
static constexpr uint32_t stop_bit = 1U << 31U;
26-
static constexpr uint32_t count_mask = stop_bit - 1;
27-
28-
public:
29-
stop_event_token() = default;
30-
stop_event_token(std::atomic<uint32_t>& token_count_, std::atomic<bool>& dtor_guard_) :
31-
token_count(&token_count_), dtor_guard(&dtor_guard_)
32-
{
33-
inc_token();
34-
}
35-
36-
stop_event_token(const stop_event_token& other) : token_count(other.token_count), dtor_guard(other.dtor_guard)
37-
{
38-
inc_token();
39-
}
40-
stop_event_token(stop_event_token&& other) noexcept :
41-
token_count(std::exchange(other.token_count, nullptr)), dtor_guard(std::exchange(other.dtor_guard, nullptr))
42-
{
43-
}
44-
45-
stop_event_token& operator=(const stop_event_token& other)
46-
{
47-
if (this != &other) {
48-
reset();
49-
token_count = other.token_count;
50-
dtor_guard = other.dtor_guard;
51-
inc_token();
52-
}
53-
return *this;
54-
}
55-
stop_event_token& operator=(stop_event_token&& other) noexcept
56-
{
57-
reset();
58-
token_count = std::exchange(other.token_count, nullptr);
59-
dtor_guard = std::exchange(other.dtor_guard, nullptr);
60-
return *this;
61-
}
62-
63-
~stop_event_token()
64-
{
65-
if (token_count != nullptr) {
66-
auto cur = token_count->fetch_sub(1, std::memory_order_acq_rel) - 1;
67-
if ((cur & count_mask) == 0) {
68-
// count reached zero.
69-
// Wake all stoppers.
70-
futex_util::wake_all(*token_count);
71-
// Update dtor guard.
72-
dtor_guard->store(false, std::memory_order_release);
73-
}
74-
token_count = nullptr;
75-
dtor_guard = nullptr;
76-
}
77-
}
78-
79-
/// Checks if the associated stop_event_source has been stopped.
80-
[[nodiscard]] bool stop_requested() const
81-
{
82-
return token_count == nullptr or (token_count->load(std::memory_order_acquire) & stop_bit) > 0;
83-
}
84-
85-
/// Destroys the observer.
86-
void reset() { stop_event_token{}.swap(*this); }
87-
88-
void swap(stop_event_token& other) noexcept
89-
{
90-
std::swap(token_count, other.token_count);
91-
std::swap(dtor_guard, other.dtor_guard);
92-
}
93-
94-
private:
95-
void inc_token()
96-
{
97-
if (token_count == nullptr) {
98-
return;
99-
}
100-
auto prev = token_count->fetch_add(1, std::memory_order_relaxed);
101-
if ((prev & count_mask) == 0) {
102-
// Transition from 0 to 1. Update dtor guard.
103-
dtor_guard->store(true, std::memory_order_release);
104-
}
105-
if (prev & stop_bit) {
106-
// Stop was already requested. Release token.
107-
reset();
108-
}
109-
}
110-
111-
std::atomic<uint32_t>* token_count = nullptr;
112-
std::atomic<bool>* dtor_guard = nullptr;
113-
};
20+
class stop_event_token;
11421

11522
/// \brief Event to signal stop to multiple observers.
11623
///
@@ -133,7 +40,7 @@ class stop_event_source
13340
}
13441

13542
/// Creates a new observer of stop() requests.
136-
[[nodiscard]] stop_event_token get_token() { return stop_event_token{token_count, dtor_guard}; }
43+
[[nodiscard]] stop_event_token get_token();
13744

13845
/// Requests all tokens to stop and blocks until all tokens are reset.
13946
void stop()
@@ -174,10 +81,94 @@ class stop_event_source
17481
[[nodiscard]] uint32_t nof_tokens_approx() const { return token_count.load(std::memory_order_relaxed) & count_mask; }
17582

17683
private:
84+
friend stop_event_token;
85+
17786
/// State variable composed by 1 MSB bit for signalling stop and 31 LSB bits for counting observers.
17887
std::atomic<uint32_t> token_count{0};
17988
/// Variable used to protect token_count from destruction when token still has to call futex wake.
18089
std::atomic<bool> dtor_guard{false};
18190
};
18291

92+
/// \brief Observer of calls to stop() on the associated stop_event_source.
93+
///
94+
/// When it gets reset or destroyed, it notifies the stop_event_source that one observer is gone.
95+
class stop_event_token
96+
{
97+
static constexpr uint32_t stop_bit = 1U << 31U;
98+
static constexpr uint32_t count_mask = stop_bit - 1;
99+
100+
public:
101+
stop_event_token() = default;
102+
explicit stop_event_token(stop_event_source& parent_) : parent(&parent_) { inc_token(); }
103+
104+
stop_event_token(const stop_event_token& other) : parent(other.parent) { inc_token(); }
105+
stop_event_token(stop_event_token&& other) noexcept : parent(std::exchange(other.parent, nullptr)) {}
106+
107+
stop_event_token& operator=(const stop_event_token& other)
108+
{
109+
if (this != &other) {
110+
reset();
111+
parent = other.parent;
112+
inc_token();
113+
}
114+
return *this;
115+
}
116+
stop_event_token& operator=(stop_event_token&& other) noexcept
117+
{
118+
reset();
119+
parent = std::exchange(other.parent, nullptr);
120+
return *this;
121+
}
122+
123+
~stop_event_token()
124+
{
125+
if (parent != nullptr) {
126+
auto cur = parent->token_count.fetch_sub(1, std::memory_order_acq_rel) - 1;
127+
if ((cur & count_mask) == 0) {
128+
// count reached zero.
129+
// Wake all stoppers.
130+
futex_util::wake_all(parent->token_count);
131+
// Update dtor guard.
132+
parent->dtor_guard.store(false, std::memory_order_release);
133+
}
134+
parent = nullptr;
135+
}
136+
}
137+
138+
/// Checks if the associated stop_event_source has been stopped.
139+
[[nodiscard]] bool stop_requested() const
140+
{
141+
return (parent == nullptr) or ((parent->token_count.load(std::memory_order_acquire) & stop_bit) > 0);
142+
}
143+
144+
/// Destroys the observer.
145+
void reset() { stop_event_token{}.swap(*this); }
146+
147+
void swap(stop_event_token& other) noexcept { std::swap(parent, other.parent); }
148+
149+
private:
150+
void inc_token()
151+
{
152+
if (parent == nullptr) {
153+
return;
154+
}
155+
auto prev = parent->token_count.fetch_add(1, std::memory_order_relaxed);
156+
if ((prev & count_mask) == 0) {
157+
// Transition from 0 to 1. Update dtor guard.
158+
parent->dtor_guard.store(true, std::memory_order_release);
159+
}
160+
if (prev & stop_bit) {
161+
// Stop was already requested. Release token.
162+
reset();
163+
}
164+
}
165+
166+
stop_event_source* parent = nullptr;
167+
};
168+
169+
inline stop_event_token stop_event_source::get_token()
170+
{
171+
return stop_event_token{*this};
172+
}
173+
183174
} // namespace srsran

0 commit comments

Comments
 (0)