• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jbaldwin / libcoro / 13476214891

22 Feb 2025 08:13PM UTC coverage: 86.445%. First build
13476214891

Pull #304

github

web-flow
Merge 1bb7b66d6 into eef5815cb
Pull Request #304: Feature/condition variable compiler fixes

119 of 136 new or added lines in 4 files covered. (87.5%)

1537 of 1778 relevant lines covered (86.45%)

3929583.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.95
/src/condition_variable.cpp
1
#include "coro/condition_variable.hpp"
2

3
#include <cassert>
4

5
namespace coro
6
{
7

8
condition_variable::condition_variable(std::shared_ptr<io_scheduler> scheduler) : m_scheduler(scheduler)
4✔
9
{
10
}
4✔
11

12
void condition_variable::notify_one() noexcept
10,002✔
13
{
14
    assert(m_scheduler);
10,002✔
15

16
    if (auto waiter_guard = extract_one())
10,002✔
17
        m_scheduler->resume(waiter_guard.value()->m_awaiting_coroutine);
10,002✔
18
}
10,002✔
19

20
void condition_variable::notify_all() noexcept
4✔
21
{
22
    assert(m_scheduler);
4✔
23

24
    if (auto waiter_guard = extract_all())
4✔
25
    {
26
        auto* waiter = waiter_guard.value();
4✔
27
        do
28
        {
29
            auto* next = waiter->m_next.load(std::memory_order::acquire);
99✔
30
            m_scheduler->resume(waiter->m_awaiting_coroutine);
99✔
31
            waiter = next;
99✔
32
        } while (waiter);
99✔
33
    }
4✔
34
}
4✔
35

36
auto condition_variable::wait(scoped_lock& lock) -> task<void>
9,993✔
37
{
38
    using namespace std::chrono_literals;
39

40
    auto mtx = lock.get_mutex();
41
    lock.unlock();
42

43
    co_await wait_for_notify();
44

45
    auto ulock = co_await mtx->lock();
46
    lock       = std::move(ulock);
47
    co_return;
48
}
19,986✔
49

NEW
50
std::shared_ptr<io_scheduler> condition_variable::scheduler() const noexcept
×
51
{
NEW
52
    return m_scheduler;
×
53
}
54

NEW
55
void condition_variable::set_scheduler(std::shared_ptr<io_scheduler> scheduler)
×
56
{
NEW
57
    m_scheduler = scheduler;
×
NEW
58
}
×
59

60
auto condition_variable::wait_for_ms(scoped_lock& lock, const std::chrono::milliseconds duration)
51✔
61
    -> task<std::cv_status>
62
{
63
    auto mtx = lock.get_mutex();
64
    lock.unlock();
65

66
    auto result = co_await m_scheduler->schedule(wait_task(this), duration);
67

68
    auto ulock = co_await mtx->lock();
69
    lock       = std::move(ulock);
70
    co_return result.has_value() ? std::cv_status::no_timeout : std::cv_status::timeout;
71
}
102✔
72

73
auto condition_variable::wait_task(condition_variable* cv) -> task<bool>
51✔
74
{
75
    co_await cv->wait_for_notify();
76
    co_return true;
77
}
102✔
78

79
void condition_variable::lock(void* ptr) noexcept
19,941✔
80
{
81
    assert(ptr);
19,941✔
82

83
    while (true)
84
    {
85
        void* unlocked{};
92,249✔
86
        if (m_lock.compare_exchange_weak(unlocked, ptr, std::memory_order::acq_rel))
92,249✔
87
            break;
19,930✔
88
    }
72,308✔
89
}
19,930✔
90

91
void condition_variable::unlock() noexcept
20,029✔
92
{
93
    m_lock.store(nullptr, std::memory_order::release);
20,029✔
94
}
20,029✔
95

96
void condition_variable::insert_waiter(wait_operation* waiter) noexcept
10,095✔
97
{
98
    while (true)
99
    {
100
        wait_operation* current = m_internal_waiters.load(std::memory_order::acquire);
10,095✔
101
        waiter->m_next.store(current, std::memory_order::release);
10,095✔
102

103
        if (!m_internal_waiters.compare_exchange_weak(current, waiter, std::memory_order::acq_rel))
10,096✔
104
            continue;
52✔
105

106
        break;
10,044✔
107
    }
52✔
108
}
10,044✔
109

110
bool condition_variable::extract_waiter(wait_operation* waiter) noexcept
10,019✔
111
{
112
    cv_lock_guard guard{this};
10,019✔
113
    bool          result{};
10,023✔
114

115
    while (true)
116
    {
117
        wait_operation* current = m_internal_waiters.load(std::memory_order::acquire);
10,023✔
118

119
        if (!current)
10,023✔
120
            break;
165✔
121

122
        wait_operation* next = current->m_next.load(std::memory_order::acquire);
9,858✔
123

124
        if (current == waiter)
9,858✔
125
        {
NEW
126
            if (!m_internal_waiters.compare_exchange_weak(current, next, std::memory_order::acq_rel))
×
NEW
127
                continue;
×
128
        }
129

130
        while (next && next != waiter)
187,532✔
131
        {
132
            current = next;
177,674✔
133
            next    = current->m_next.load(std::memory_order::acquire);
177,674✔
134
        }
135

136
        if (!next)
9,858✔
137
            break;
9,858✔
138

NEW
139
        wait_operation* new_next = waiter->m_next.load(std::memory_order::acquire);
×
140

NEW
141
        if (!current->m_next.compare_exchange_strong(next, new_next, std::memory_order::acq_rel))
×
NEW
142
            continue;
×
143

NEW
144
        waiter->m_next.store(nullptr, std::memory_order::release);
×
NEW
145
        result = true;
×
NEW
146
        break;
×
NEW
147
    }
×
148

149
    return result;
20,046✔
150
}
10,023✔
151

152
condition_variable::wait_operation_guard condition_variable::extract_all()
4✔
153
{
154
    wait_operation_guard result{this};
4✔
155

156
    while (true)
157
    {
158
        auto* current = m_internal_waiters.load(std::memory_order::acquire);
4✔
159
        if (!current)
4✔
NEW
160
            break;
×
161

162
        if (!m_internal_waiters.compare_exchange_weak(current, nullptr, std::memory_order::acq_rel))
4✔
NEW
163
            continue;
×
164

165
        result.set_value(current);
4✔
166
        break;
4✔
NEW
167
    }
×
168

169
    return result;
4✔
170
}
171

172
condition_variable::wait_operation_guard condition_variable::extract_one()
10,002✔
173
{
174
    wait_operation_guard result{this};
10,002✔
175

176
    while (true)
177
    {
178
        auto* current = m_internal_waiters.load(std::memory_order::acquire);
10,027✔
179
        if (!current)
10,027✔
180
            break;
78✔
181

182
        auto* next = current->m_next.load(std::memory_order::acquire);
9,949✔
183
        if (!m_internal_waiters.compare_exchange_weak(current, next, std::memory_order::acq_rel))
9,949✔
184
            continue;
25✔
185

186
        current->m_next.store(nullptr, std::memory_order::release);
9,924✔
187
        result.set_value(current);
9,924✔
188
        break;
9,924✔
189
    }
25✔
190

191
    return result;
10,002✔
192
}
193

194
condition_variable::wait_operation::wait_operation(condition_variable& cv) : m_condition_variable(cv)
10,044✔
195
{
196
}
10,044✔
197

198
condition_variable::wait_operation::~wait_operation()
10,017✔
199
{
200
    m_condition_variable.extract_waiter(this);
10,017✔
201
}
10,023✔
202

203
auto condition_variable::wait_operation::await_suspend(std::coroutine_handle<> awaiting_coroutine) noexcept -> bool
10,044✔
204
{
205
    m_awaiting_coroutine = awaiting_coroutine;
10,044✔
206
    m_condition_variable.insert_waiter(this);
10,044✔
207
    return true;
10,044✔
208
}
209

210
void condition_variable::wait_operation::await_resume() noexcept
10,018✔
211
{
212
}
10,018✔
213

214
condition_variable::cv_lock_guard::cv_lock_guard(condition_variable* cv) noexcept : m_cv(cv)
19,921✔
215
{
216
    m_cv->lock(m_cv);
19,921✔
217
}
20,029✔
218

219
coro::condition_variable::cv_lock_guard::~cv_lock_guard() noexcept
20,029✔
220
{
221
    m_cv->unlock();
20,029✔
222
}
20,028✔
223

224
condition_variable::wait_operation_guard::wait_operation_guard(condition_variable* cv, wait_operation* value) noexcept
10,006✔
225
    : cv_lock_guard(cv),
226
      m_value(value)
10,006✔
227
{
228
}
10,006✔
229

230
condition_variable::wait_operation_guard::operator bool() const noexcept
10,006✔
231
{
232
    return m_value;
10,006✔
233
}
234

235
void condition_variable::wait_operation_guard::set_value(wait_operation* value) noexcept
9,928✔
236
{
237
    m_value = value;
9,928✔
238
}
9,928✔
239

240
condition_variable::wait_operation* condition_variable::wait_operation_guard::value() const noexcept
9,928✔
241
{
242
    return m_value;
9,928✔
243
}
244

245
} // namespace coro
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc