-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathgcd.cpp
97 lines (82 loc) · 3.42 KB
/
gcd.cpp
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* @author github.com/luncliff (luncliff@gmail.com)
*/
#include "gcd.hpp"
#include <spdlog/spdlog.h>
namespace coro {
void sink_exception(const spdlog::source_loc& loc, std::exception_ptr&& exp) noexcept {
try {
std::rethrow_exception(exp);
} catch (const std::exception& ex) {
spdlog::log(loc, spdlog::level::err, ex.what());
} catch (const std::error_code& ex) {
spdlog::log(loc, spdlog::level::err, ex.message());
} catch (const std::error_condition& ex) {
spdlog::log(loc, spdlog::level::err, ex.message());
} catch (...) {
spdlog::log(loc, spdlog::level::critical, "unknwon exception type detected");
}
}
void queue_awaitable_t::await_suspend(coroutine_handle<void> coro) noexcept {
dispatch_async_f(queue, coro.address(), resume_once);
}
semaphore_owner_t::semaphore_owner_t() noexcept(false) : sem{dispatch_semaphore_create(0)} {
}
semaphore_owner_t::semaphore_owner_t(dispatch_semaphore_t handle) noexcept(false) : sem{handle} {
if (handle == nullptr)
throw std::invalid_argument{__func__};
dispatch_retain(sem);
}
semaphore_owner_t::~semaphore_owner_t() noexcept {
dispatch_release(sem);
}
semaphore_owner_t::semaphore_owner_t(const semaphore_owner_t& rhs) noexcept : semaphore_owner_t{rhs.sem} {
}
/// @note change the `promise_type`'s handle before `initial_suspend`
semaphore_action_t::semaphore_action_t(promise_type& p) noexcept
// We have to share the semaphore between coroutine frame and return instance.
// If `promise_type` is created with multiple arguments, the handle won't be nullptr.
: sem{p.semaphore ? p.semaphore : dispatch_semaphore_create(0)} {
// When the compiler default-constructed the `promise_type`, its semaphore will be nullptr.
if (p.semaphore == nullptr) {
// Share a newly created one
p.semaphore = sem.handle();
// We used dispatch_semaphore_create above.
// The reference count is higher than what we want
dispatch_release(p.semaphore);
}
}
void semaphore_action_t::promise_type::unhandled_exception() noexcept {
spdlog::source_loc loc{"semaphore_action_t", __LINE__, __func__};
sink_exception(loc, std::current_exception());
}
void group_action_t::promise_type::unhandled_exception() noexcept {
spdlog::source_loc loc{"group_action_t", __LINE__, __func__};
sink_exception(loc, std::current_exception());
}
void timer_owner_t::set(void* context, dispatch_function_t on_event, dispatch_function_t on_cancel) noexcept {
dispatch_set_context(source, context);
dispatch_source_set_event_handler_f(source, on_event);
dispatch_source_set_cancel_handler_f(source, on_cancel);
}
void timer_owner_t::start(std::chrono::nanoseconds interval, dispatch_time_t start) noexcept {
using namespace std::chrono;
using namespace std::chrono_literals;
dispatch_source_set_timer(source, start, interval.count(), duration_cast<nanoseconds>(500us).count());
return dispatch_resume(source);
}
bool timer_owner_t::cancel(void* context, dispatch_function_t on_cancel) noexcept {
if (context)
dispatch_set_context(source, context);
if (on_cancel)
dispatch_source_set_cancel_handler_f(source, on_cancel);
// cancel after check
if (dispatch_source_testcancel(source) != 0)
return false;
dispatch_source_cancel(source);
return true;
}
void timer_owner_t::suspend() noexcept {
dispatch_suspend(source);
}
} // namespace coro