/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2013 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/kernel/xevent.h" #include "xenia/base/byte_stream.h" #include "xenia/base/logging.h" namespace xe { namespace kernel { XEvent::XEvent(KernelState* kernel_state) : XObject(kernel_state, kTypeEvent) {} XEvent::~XEvent() = default; void XEvent::Initialize(bool manual_reset, bool initial_state) { assert_false(event_); this->CreateNative(); if (manual_reset) { event_ = xe::threading::Event::CreateManualResetEvent(initial_state); } else { event_ = xe::threading::Event::CreateAutoResetEvent(initial_state); } } void XEvent::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { assert_false(event_); switch (header->type) { case 0x00: // EventNotificationObject (manual reset) manual_reset_ = true; break; case 0x01: // EventSynchronizationObject (auto reset) manual_reset_ = false; break; default: assert_always(); return; } bool initial_state = header->signal_state ? true : false; if (manual_reset_) { event_ = xe::threading::Event::CreateManualResetEvent(initial_state); } else { event_ = xe::threading::Event::CreateAutoResetEvent(initial_state); } } int32_t XEvent::Set(uint32_t priority_increment, bool wait) { event_->Set(); return 1; } int32_t XEvent::Pulse(uint32_t priority_increment, bool wait) { event_->Pulse(); return 1; } int32_t XEvent::Reset() { event_->Reset(); return 1; } void XEvent::Clear() { event_->Reset(); } bool XEvent::Save(ByteStream* stream) { XELOGD("XEvent %.8X (%s)", handle(), manual_reset_ ? "manual" : "auto"); SaveObject(stream); bool signaled = true; auto result = xe::threading::Wait(event_.get(), false, std::chrono::milliseconds(0)); if (result == xe::threading::WaitResult::kSuccess) { signaled = true; } else if (result == xe::threading::WaitResult::kTimeout) { signaled = false; } else { assert_always(); } if (signaled) { // Reset the event in-case it's an auto-reset. event_->Set(); } stream->Write(signaled); stream->Write(manual_reset_); return true; } object_ref XEvent::Restore(KernelState* kernel_state, ByteStream* stream) { auto evt = new XEvent(nullptr); evt->kernel_state_ = kernel_state; evt->RestoreObject(stream); bool signaled = stream->Read(); evt->manual_reset_ = stream->Read(); if (evt->manual_reset_) { evt->event_ = xe::threading::Event::CreateManualResetEvent(false); } else { evt->event_ = xe::threading::Event::CreateAutoResetEvent(false); } if (signaled) { evt->event_->Set(); } evt->Retain(); return object_ref(evt); } } // namespace kernel } // namespace xe