-
Notifications
You must be signed in to change notification settings - Fork 4
/
Scope.h
71 lines (58 loc) · 1.76 KB
/
Scope.h
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
#pragma once
#include "CoFiber.h"
#include "Task.h"
#include <map>
#include <string>
#include <variant>
struct ScopeVariable {
int value = {};
};
struct ScopeWaiter {
CoFiber fiber{};
std::coroutine_handle<> coroutine{};
auto resume() {
fiber.run([this] { coroutine.resume(); });
}
};
struct ScopeAwaiter {
ScopeWaiter &m_slot;
bool await_ready() const noexcept { return false; }
void await_resume() const noexcept {}
template<class Promise>
auto await_suspend(std::coroutine_handle<Promise> awaitingCoroutine) const noexcept
-> std::coroutine_handle<> {
m_slot.coroutine = awaitingCoroutine;
m_slot.fiber = CoFiber::current;
return std::noop_coroutine();
}
};
struct Scope {
using IdVariables = std::map<std::string, ScopeVariable, std::less<>>;
using Waiters = std::vector<ScopeWaiter>;
using IdWaiters = std::map<std::string, Waiters, std::less<>>;
IdVariables m_variables;
IdWaiters m_waiters;
using QueryResult = std::variant<std::monostate, const ScopeVariable *>;
auto query(const std::string_view &id) const -> QueryResult {
if (auto it = m_variables.find(id); it != m_variables.end()) {
return &it->second;
}
return {};
}
auto waitFor(std::string id) -> ScopeAwaiter {
return ScopeAwaiter{m_waiters[std::move(id)].emplace_back()};
}
void defineVariable(std::string id) {
auto [it, inserted] = m_variables.emplace(std::move(id), ScopeVariable{});
if (!inserted) {
throw "fail!";
}
auto key = std::string_view{it->first};
if (auto it = m_waiters.find(key); it != m_waiters.end()) {
for (auto &waiter : it->second) {
waiter.resume();
}
m_waiters.erase(it);
}
}
};