diff options
| author | DrChat <arkolbed@gmail.com> | 2017-12-20 17:51:31 -0600 |
|---|---|---|
| committer | DrChat <arkolbed@gmail.com> | 2017-12-20 17:51:31 -0600 |
| commit | a47417117ee027e029bd82d34bb88323737ec7dd (patch) | |
| tree | 203fedf50d3da6415daec2e961c97fe5540625ff | |
| parent | c4cd5dee19a2d58c3535706577c5fe177a92d720 (diff) | |
[Base] Implement PosixEvent using eventfd
| -rw-r--r-- | src/xenia/base/threading_posix.cc | 64 |
1 files changed, 57 insertions, 7 deletions
diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 7570a824a..926f4943d 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -13,6 +13,7 @@ #include "xenia/base/logging.h" #include <pthread.h> +#include <sys/eventfd.h> #include <sys/syscall.h> #include <sys/time.h> #include <sys/types.h> @@ -204,11 +205,51 @@ class PosixConditionHandle : public T { PosixCondition handle_; }; +template <typename T> +class PosixFdHandle : public T { + public: + explicit PosixFdHandle(intptr_t handle) : handle_(handle) {} + ~PosixFdHandle() override { + close(handle_); + handle_ = 0; + } + + protected: + void* native_handle() const override { + return reinterpret_cast<void*>(handle_); + } + + intptr_t handle_; +}; + // TODO(dougvj) WaitResult Wait(WaitHandle* wait_handle, bool is_alertable, std::chrono::milliseconds timeout) { - assert_always(); - return WaitResult::kFailed; + intptr_t handle = reinterpret_cast<intptr_t>(wait_handle->native_handle()); + + fd_set set; + struct timeval time_val; + int ret; + + FD_ZERO(&set); + FD_SET(handle, &set); + + time_val.tv_sec = timeout.count() / 1000; + time_val.tv_usec = timeout.count() * 1000; + ret = select(handle + 1, &set, NULL, NULL, &time_val); + if (ret == -1) { + return WaitResult::kFailed; + } else if (ret == 0) { + return WaitResult::kTimeout; + } else { + uint64_t buf = 0; + ret = read(handle, &buf, sizeof(buf)); + if (ret < 8) { + return WaitResult::kTimeout; + } + + return WaitResult::kSuccess; + } } // TODO(dougvj) @@ -229,11 +270,14 @@ std::pair<WaitResult, size_t> WaitMultiple(WaitHandle* wait_handles[], } // TODO(dougvj) -class PosixEvent : public PosixConditionHandle<Event> { +class PosixEvent : public PosixFdHandle<Event> { public: - PosixEvent(bool initial_state, int auto_reset) { assert_always(); } + PosixEvent(intptr_t fd) : PosixFdHandle(fd) {} ~PosixEvent() override = default; - void Set() override { assert_always(); } + void Set() override { + uint64_t buf = 1; + write(handle_, &buf, sizeof(buf)); + } void Reset() override { assert_always(); } void Pulse() override { assert_always(); } @@ -242,11 +286,17 @@ class PosixEvent : public PosixConditionHandle<Event> { }; std::unique_ptr<Event> Event::CreateManualResetEvent(bool initial_state) { - return std::make_unique<PosixEvent>(PosixEvent(initial_state, false)); + // Linux's eventfd doesn't appear to support manual reset natively. + return nullptr; } std::unique_ptr<Event> Event::CreateAutoResetEvent(bool initial_state) { - return std::make_unique<PosixEvent>(PosixEvent(initial_state, true)); + int fd = eventfd(initial_state ? 1 : 0, EFD_CLOEXEC); + if (fd == -1) { + return nullptr; + } + + return std::make_unique<PosixEvent>(PosixEvent(fd)); } // TODO(dougvj) |
