-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathsync.cpp
More file actions
72 lines (59 loc) · 2.11 KB
/
sync.cpp
File metadata and controls
72 lines (59 loc) · 2.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "eventide/async/runtime/sync.h"
#include <cassert>
namespace eventide {
void sync_primitive::insert(waiter_link* link) {
assert(link && "insert: null waiter_link");
assert(link->resource == nullptr && "insert: waiter_link already linked");
assert(link->prev == nullptr && link->next == nullptr && "insert: waiter_link has links");
link->resource = this;
// Snapshot semantics for interrupt() depend on each waiter remembering the
// generation that was current when it joined the queue.
link->generation = waiter_generation;
if(tail) {
tail->next = link;
link->prev = tail;
tail = link;
} else {
head = link;
tail = link;
}
}
void sync_primitive::remove(waiter_link* link) {
assert(link && "remove: null waiter_link");
assert(link->resource == this && "remove: waiter_link not owned by resource");
if(link->prev) {
link->prev->next = link->next;
} else {
head = link->next;
}
if(link->next) {
link->next->prev = link->prev;
} else {
tail = link->prev;
}
link->prev = nullptr;
link->next = nullptr;
link->resource = nullptr;
}
bool sync_primitive::cancel_waiter(waiter_link* link) noexcept {
if(!link) {
return false;
}
auto* awaiting = link->awaiter;
link->awaiter = nullptr;
if(!awaiting || awaiting->is_cancelled()) {
return false;
}
// This callback may resume arbitrary user code immediately. In particular,
// that code may enqueue a brand-new waiter on the same resource, or even
// destroy other waiters that used to be siblings of `link`. That is why
// interrupt() must process the queue in-place with generation checks rather
// than first stashing raw waiter pointers into a temporary container.
link->state = async_node::Cancelled;
link->policy = static_cast<async_node::Policy>(link->policy | async_node::InterceptCancel);
auto* prev = detail::current_node();
auto next = awaiting->handle_subtask_result(link);
detail::resume_and_drain(prev, next);
return true;
}
} // namespace eventide