File linux.h¶
File List > coroutine > linux.h
Go to the documentation of this file.
#ifndef COROUTINE_SYSTEM_WRAPPER_H
#define COROUTINE_SYSTEM_WRAPPER_H
#if !(defined(__linux__))
#error "expect Linux platform for this file"
#endif
#include <sys/epoll.h> // for Linux epoll
#include <coroutine/return.h>
#include <gsl/gsl>
namespace coro {
class epoll_owner final {
int64_t epfd;
public:
epoll_owner() noexcept(false);
~epoll_owner() noexcept;
epoll_owner(const epoll_owner&) = delete;
epoll_owner(epoll_owner&&) = delete;
epoll_owner& operator=(const epoll_owner&) = delete;
epoll_owner& operator=(epoll_owner&&) = delete;
public:
void try_add(uint64_t fd, epoll_event& req) noexcept(false);
void remove(uint64_t fd);
ptrdiff_t wait(uint32_t wait_ms,
gsl::span<epoll_event> list) noexcept(false);
public:
[[nodiscard]] auto submit(int64_t fd, epoll_event& req) noexcept {
class awaiter final : public suspend_always {
epoll_owner& ep;
int64_t fd;
epoll_event& req;
public:
constexpr awaiter(epoll_owner& _ep, int64_t _fd, epoll_event& _req)
: ep{_ep}, fd{_fd}, req{_req} {
}
public:
void await_suspend(coroutine_handle<void> coro) noexcept(false) {
if (req.data.ptr == nullptr)
req.data.ptr = coro.address();
return ep.try_add(fd, req);
}
};
return awaiter{*this, fd, req};
}
};
class event final {
uint64_t state;
public:
event() noexcept(false);
~event() noexcept;
event(const event&) = delete;
event(event&&) = delete;
event& operator=(const event&) = delete;
event& operator=(event&&) = delete;
uint64_t fd() const noexcept;
bool is_set() const noexcept;
void set() noexcept(false);
void reset() noexcept(false);
};
auto wait_in(epoll_owner& ep, event& efd) {
class awaiter : epoll_event {
epoll_owner& ep;
event& efd;
public:
awaiter(epoll_owner& _ep, event& _efd) noexcept
: epoll_event{}, ep{_ep}, efd{_efd} {
this->events = EPOLLET | EPOLLIN | EPOLLONESHOT;
}
bool await_ready() const noexcept {
return efd.is_set();
}
void await_suspend(coroutine_handle<void> coro) noexcept(false) {
this->data.ptr = coro.address();
return ep.try_add(efd.fd(), *this);
}
void await_resume() noexcept {
return efd.reset();
}
};
return awaiter{ep, efd};
}
} // namespace coro
#endif // COROUTINE_SYSTEM_WRAPPER_H