Created
May 29, 2020 23:02
-
-
Save qookei/197fb68f1d5398bf2af0a62f32cb1074 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct timerfd final : file { | |
static auto create_timer(reactor *rtor_) { | |
return new timerfd{rtor_}; | |
} | |
timerfd(reactor *rtor) | |
: file{rtor, timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)}, current_{} { } | |
// ---------------------------------------------------------------------------------- | |
// Sleep boilerplate. | |
// ---------------------------------------------------------------------------------- | |
private: | |
struct sleep_base { | |
friend struct timerfd; | |
sleep_base(timespec t) | |
: t_{t} { } | |
protected: | |
~sleep_base() = default; | |
virtual void complete() = 0; | |
private: | |
timespec t_; | |
}; | |
public: | |
struct [[nodiscard]] sleep_sender { | |
timerfd *fd; | |
timespec t; | |
}; | |
sleep_sender async_sleep(timespec t) { | |
assert(!current_ && "one timerfd can only be used for one sleep at a time"); | |
return {this, t}; | |
} | |
template<typename Receiver> | |
struct sleep_operation final : sleep_base { | |
friend struct timerfd; | |
sleep_operation(sleep_sender s, Receiver r) | |
: sleep_base{s.t}, fd_{s.fd}, r_{std::move(r)} { } | |
void start() { | |
itimerspec ts{.it_value = t_, .it_interval = {}}; | |
timerfd_settime(fd_->get_fd(), 0, &ts, nullptr); | |
fd_->current_ = this; | |
} | |
protected: | |
void complete() override { | |
fd_->current_ = nullptr; | |
r_.set_value(); | |
} | |
private: | |
timerfd *fd_; | |
Receiver r_; | |
}; | |
template<typename Receiver> | |
friend sleep_operation<Receiver> connect(sleep_sender s, Receiver r) { | |
return {s, std::move(r)}; | |
} | |
friend async::sender_awaiter<sleep_sender, void> | |
operator co_await(sleep_sender s) { | |
return {s}; | |
}; | |
protected: | |
void on_readable() override { | |
assert(current_); | |
current_->complete(); | |
} | |
void on_writable() override { } | |
private: | |
sleep_base *current_; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment