diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/cru/base/Base.h | 1 | ||||
-rw-r--r-- | include/cru/base/platform/unix/EventLoop.h | 95 | ||||
-rw-r--r-- | include/cru/base/platform/unix/Timer.h | 43 |
3 files changed, 96 insertions, 43 deletions
diff --git a/include/cru/base/Base.h b/include/cru/base/Base.h index fd409360..f8f8c8c0 100644 --- a/include/cru/base/Base.h +++ b/include/cru/base/Base.h @@ -93,6 +93,7 @@ struct CRU_BASE_API Interface { }; [[noreturn]] void CRU_BASE_API UnreachableCode(); +[[noreturn]] void CRU_BASE_API NotImplemented(); using Index = std::ptrdiff_t; diff --git a/include/cru/base/platform/unix/EventLoop.h b/include/cru/base/platform/unix/EventLoop.h new file mode 100644 index 00000000..bc2bcbf8 --- /dev/null +++ b/include/cru/base/platform/unix/EventLoop.h @@ -0,0 +1,95 @@ +#pragma once + +#include <optional> +#if !defined(__unix) && !defined(__APPLE__) +#error "This file can only be included on unix." +#endif + +#include "../../Base.h" +#include "../../Exception.h" +#include "UnixFile.h" + +#include <unistd.h> +#include <chrono> +#include <thread> + +namespace cru::platform::unix { +class UnixTimerFile : public Object2 { + public: + template <class Rep, class Period> + explicit UnixTimerFile(std::chrono::duration<Rep, Period> time) { + auto fds = OpenUniDirectionalPipe(); + this->read_fd_ = std::move(fds.read); + this->write_fd_ = std::move(fds.write); + + this->thread_ = std::thread([this, time] { + std::this_thread::sleep_for(time); + constexpr auto buffer = ""; + auto written = ::write(this->write_fd_, buffer, 1); + if (written != 1) { + throw Exception( + "Failed to write to pipe in UnixTimerFile thread at timeout."); + } + }); + this->thread_.detach(); + } + + int GetReadFd() const; + + private: + UnixFileDescriptor write_fd_; + UnixFileDescriptor read_fd_; + std::thread thread_; +}; + +class UnixEventLoop : public Object2 { + public: + UnixEventLoop(); + + int Run(); + void RequestQuit(int exit_code = 0); + + int SetTimer(std::function<void()> action, std::chrono::milliseconds timeout, + bool repeat); + + int SetImmediate(std::function<void()> action) { + return this->SetTimer(std::move(action), std::chrono::milliseconds::zero(), + false); + } + + int SetTimeout(std::function<void()> action, + std::chrono::milliseconds timeout) { + return this->SetTimer(std::move(action), std::move(timeout), false); + } + + int SetInterval(std::function<void()> action, + std::chrono::milliseconds interval) { + return this->SetTimer(std::move(action), std::move(interval), true); + } + + private: + struct TimerData { + int id; + std::chrono::milliseconds original_timeout; + std::chrono::milliseconds timeout; + bool repeat; + std::function<void()> action; + + TimerData(int id, std::chrono::milliseconds timeout, bool repeat, + std::function<void()> action) + : id(id), + original_timeout(timeout), + timeout(timeout), + repeat(repeat), + action(std::move(action)) {} + }; + + std::thread::id running_thread_; + + std::atomic_int timer_tag_; + std::vector<TimerData> timers_; + + std::optional<int> exit_code_; +}; + +} // namespace cru::platform::unix diff --git a/include/cru/base/platform/unix/Timer.h b/include/cru/base/platform/unix/Timer.h deleted file mode 100644 index 17abd1cc..00000000 --- a/include/cru/base/platform/unix/Timer.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#if !defined(__unix) && !defined(__APPLE__) -#error "This file can only be included on unix." -#endif - -#include "../../Base.h" -#include "../../Exception.h" -#include "UnixFile.h" - -#include <chrono> -#include <thread> -#include <unistd.h> - -namespace cru::platform::unix { -class UnixTimerFile : public Object2 { - public: - template <class Rep, class Period> - explicit UnixTimerFile(std::chrono::duration<Rep, Period> time) { - auto fds = OpenUniDirectionalPipe(); - this->read_fd_ = std::move(fds.read); - this->write_fd_ = std::move(fds.write); - - this->thread_ = std::thread([this, time] { - std::this_thread::sleep_for(time); - constexpr auto buffer = ""; - auto written = ::write(this->write_fd_, buffer, 1); - if (written != 1) { - throw Exception( - "Failed to write to pipe in UnixTimerFile thread at timeout."); - } - }); - this->thread_.detach(); - } - - int GetReadFd() const; - - private: - UnixFileDescriptor write_fd_; - UnixFileDescriptor read_fd_; - std::thread thread_; -}; -} // namespace cru::platform::unix |