// Copyright Epic Games, Inc. All Rights Reserved. #include #include #include #include #include #include namespace zen { void RwLock::AcquireShared() { AcquireSRWLockShared((PSRWLOCK)&m_Srw); } void RwLock::ReleaseShared() { ReleaseSRWLockShared((PSRWLOCK)&m_Srw); } void RwLock::AcquireExclusive() { AcquireSRWLockExclusive((PSRWLOCK)&m_Srw); } void RwLock::ReleaseExclusive() { ReleaseSRWLockExclusive((PSRWLOCK)&m_Srw); } Event::Event() { m_EventHandle = CreateEvent(nullptr, true, false, nullptr); } Event::~Event() { CloseHandle(m_EventHandle); } void Event::Set() { SetEvent(m_EventHandle); } void Event::Reset() { ResetEvent(m_EventHandle); } bool Event::Wait(int TimeoutMs) { using namespace std::literals; const DWORD Timeout = (TimeoutMs < 0) ? INFINITE : TimeoutMs; DWORD Result = WaitForSingleObject(m_EventHandle, Timeout); if (Result == WAIT_FAILED) { zen::ThrowLastError("Event wait failed"sv); } return (Result == WAIT_OBJECT_0); } NamedEvent::NamedEvent(std::u8string_view EventName) : Event(nullptr) { using namespace std::literals; ExtendableStringBuilder<64> Name; Name << "Local\\"sv; Name << EventName; m_EventHandle = CreateEventA(nullptr, true, false, Name.c_str()); } NamedEvent::NamedEvent(std::string_view EventName) : Event(nullptr) { using namespace std::literals; ExtendableStringBuilder<64> Name; Name << "Local\\"sv; Name << EventName; m_EventHandle = CreateEventA(nullptr, true, false, Name.c_str()); } NamedMutex::~NamedMutex() { if (m_MutexHandle) { CloseHandle(m_MutexHandle); } } bool NamedMutex::Create(std::string_view MutexName) { ZEN_ASSERT(m_MutexHandle == nullptr); using namespace std::literals; ExtendableStringBuilder<64> Name; Name << "Global\\"sv; Name << MutexName; m_MutexHandle = CreateMutexA(nullptr, /* InitialOwner */ TRUE, Name.c_str()); return !!m_MutexHandle; } bool NamedMutex::Exists(std::string_view MutexName) { using namespace std::literals; ExtendableStringBuilder<64> Name; Name << "Global\\"sv; Name << MutexName; void* MutexHandle = OpenMutexA(SYNCHRONIZE, /* InheritHandle */ FALSE, Name.c_str()); if (MutexHandle == nullptr) { return false; } CloseHandle(MutexHandle); return true; } ProcessHandle::ProcessHandle() = default; void ProcessHandle::Initialize(void* ProcessHandle) { ZEN_ASSERT(m_ProcessHandle == nullptr); // TODO: perform some debug verification here to verify it's a valid handle? m_ProcessHandle = ProcessHandle; } ProcessHandle::~ProcessHandle() { Reset(); } void ProcessHandle::Initialize(int Pid) { ZEN_ASSERT(m_ProcessHandle == nullptr); m_ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, Pid); using namespace fmt::literals; if (!m_ProcessHandle) { ThrowLastError("ProcessHandle::Initialize(pid: {}) failed"_format(Pid)); } m_Pid = Pid; } bool ProcessHandle::IsRunning() const { DWORD ExitCode = 0; GetExitCodeProcess(m_ProcessHandle, &ExitCode); return ExitCode == STILL_ACTIVE; } bool ProcessHandle::IsValid() const { return (m_ProcessHandle != nullptr) && (m_ProcessHandle != INVALID_HANDLE_VALUE); } void ProcessHandle::Terminate(int ExitCode) { if (IsRunning()) { TerminateProcess(m_ProcessHandle, ExitCode); } DWORD WaitResult = WaitForSingleObject(m_ProcessHandle, INFINITE); if (WaitResult != WAIT_OBJECT_0) { // What might go wrong here, and what is meaningful to act on? } } void ProcessHandle::Reset() { if (IsValid()) { CloseHandle(m_ProcessHandle); m_ProcessHandle = nullptr; } } bool ProcessHandle::Wait(int TimeoutMs) { const DWORD Timeout = (TimeoutMs < 0) ? INFINITE : TimeoutMs; const DWORD WaitResult = WaitForSingleObject(m_ProcessHandle, Timeout); switch (WaitResult) { case WAIT_OBJECT_0: return true; case WAIT_TIMEOUT: return false; case WAIT_FAILED: // What might go wrong here, and what is meaningful to act on? throw WindowsException("Process::Wait failed"); } return false; } bool IsProcessRunning(int pid) { HANDLE hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); if (hProc == NULL) { return false; } CloseHandle(hProc); return true; } int GetCurrentProcessId() { return ::GetCurrentProcessId(); } void Sleep(int ms) { ::Sleep(ms); } ////////////////////////////////////////////////////////////////////////// // // Testing related code follows... // void thread_forcelink() { } } // namespace zen