From 1b838c4403fbd2273237d7129c07c7bcbebedaf2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Aug 2013 09:08:31 -0700 Subject: [PATCH] Move ThreadEventQueue to its own file. --- CMakeLists.txt | 1 + Core/Core.vcxproj | 1 + Core/Core.vcxproj.filters | 3 + Core/ThreadEventQueue.h | 116 ++++++++++++++++++++++++++++++++++++++ GPU/GPUCommon.h | 97 +------------------------------ 5 files changed, 122 insertions(+), 96 deletions(-) create mode 100644 Core/ThreadEventQueue.h diff --git a/CMakeLists.txt b/CMakeLists.txt index aba6a9d71a..36f71bfb8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -746,6 +746,7 @@ add_library(${CoreLibName} ${CoreLinkType} Core/CwCheat.h Core/HDRemaster.cpp Core/HDRemaster.h + Core/ThreadEventQueue.h Core/Debugger/Breakpoints.cpp Core/Debugger/Breakpoints.h Core/Debugger/DebugInterface.h diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 2ac6129b66..1416bbb4d0 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -486,6 +486,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index ae1395a957..d9861b0b99 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -837,6 +837,9 @@ FileSystems + + Core + diff --git a/Core/ThreadEventQueue.h b/Core/ThreadEventQueue.h new file mode 100644 index 0000000000..11231ea6ac --- /dev/null +++ b/Core/ThreadEventQueue.h @@ -0,0 +1,116 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "native/base/mutex.h" +#include "Core/CoreTiming.h" +#include + +template +struct ThreadEventQueue : public B { + void SetThreadEnabled(bool threadEnabled) { + threadEnabled_ = threadEnabled; + } + + void ScheduleEvent(Event ev) { + { + lock_guard guard(eventsLock_); + events_.push_back(ev); + eventsWait_.notify_one(); + } + + if (!threadEnabled_) { + RunEventsUntil(0); + } + } + + bool HasEvents() { + lock_guard guard(eventsLock_); + return !events_.empty(); + } + + Event GetNextEvent() { + lock_guard guard(eventsLock_); + if (events_.empty()) { + eventsDrain_.notify_one(); + return EVENT_INVALID; + } + + Event ev = events_.front(); + events_.pop_front(); + return ev; + } + + void RunEventsUntil(u64 globalticks) { + do { + for (Event ev = GetNextEvent(); EventType(ev) != EVENT_INVALID; ev = GetNextEvent()) { + switch (EventType(ev)) { + case EVENT_FINISH: + // Stop waiting. + globalticks = 0; + break; + + case EVENT_SYNC: + break; + + default: + ProcessEvent(ev); + } + } + + // Quit the loop if the queue is drained and coreState has tripped, or threading is disabled. + if (coreState != CORE_RUNNING || !threadEnabled_) { + return; + } + + // coreState changes won't wake us, so recheck periodically. + eventsWait_.wait_for(eventsWaitLock_, 1); + } while (CoreTiming::GetTicks() < globalticks); + } + + void SyncThread() { + if (!threadEnabled_) { + return; + } + + // While processing the last event, HasEvents() will be false even while not done. + // So we schedule a nothing event and wait for that to finish. + ScheduleEvent(EVENT_SYNC); + while (HasEvents() && coreState == CORE_RUNNING) { + eventsDrain_.wait_for(eventsDrainLock_, 1); + } + } + + void FinishEventLoop() { + if (threadEnabled_) { + ScheduleEvent(EVENT_FINISH); + } + } + +protected: + virtual void ProcessEvent(Event ev) = 0; + +private: + bool threadEnabled_; + std::deque events_; + recursive_mutex eventsLock_; + recursive_mutex eventsWaitLock_; + recursive_mutex eventsDrainLock_; + condition_variable eventsWait_; + condition_variable eventsDrain_; +}; \ No newline at end of file diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index b274f7e820..927a50e57a 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -1,103 +1,8 @@ #pragma once -#include "native/base/mutex.h" +#include "Core/ThreadEventQueue.h" #include "GPU/GPUInterface.h" -#include "Core/CoreTiming.h" -#include -template -struct ThreadEventQueue : public B { - void SetThreadEnabled(bool threadEnabled) { - threadEnabled_ = threadEnabled; - } - - void ScheduleEvent(Event ev) { - { - lock_guard guard(eventsLock_); - events_.push_back(ev); - eventsWait_.notify_one(); - } - - if (!threadEnabled_) { - RunEventsUntil(0); - } - } - - bool HasEvents() { - lock_guard guard(eventsLock_); - return !events_.empty(); - } - - Event GetNextEvent() { - lock_guard guard(eventsLock_); - if (events_.empty()) { - eventsDrain_.notify_one(); - return EVENT_INVALID; - } - - Event ev = events_.front(); - events_.pop_front(); - return ev; - } - - void RunEventsUntil(u64 globalticks) { - do { - for (Event ev = GetNextEvent(); EventType(ev) != EVENT_INVALID; ev = GetNextEvent()) { - switch (EventType(ev)) { - case EVENT_FINISH: - // Stop waiting. - globalticks = 0; - break; - - case EVENT_SYNC: - break; - - default: - ProcessEvent(ev); - } - } - - // Quit the loop if the queue is drained and coreState has tripped, or threading is disabled. - if (coreState != CORE_RUNNING || !threadEnabled_) { - return; - } - - // coreState changes won't wake us, so recheck periodically. - eventsWait_.wait_for(eventsWaitLock_, 1); - } while (CoreTiming::GetTicks() < globalticks); - } - - void SyncThread() { - if (!threadEnabled_) { - return; - } - - // While processing the last event, HasEvents() will be false even while not done. - // So we schedule a nothing event and wait for that to finish. - ScheduleEvent(EVENT_SYNC); - while (HasEvents() && coreState == CORE_RUNNING) { - eventsDrain_.wait_for(eventsDrainLock_, 1); - } - } - - void FinishEventLoop() { - if (threadEnabled_) { - ScheduleEvent(EVENT_FINISH); - } - } - -protected: - virtual void ProcessEvent(Event ev) = 0; - -private: - bool threadEnabled_; - std::deque events_; - recursive_mutex eventsLock_; - recursive_mutex eventsWaitLock_; - recursive_mutex eventsDrainLock_; - condition_variable eventsWait_; - condition_variable eventsDrain_; -}; typedef ThreadEventQueue GPUThreadEventQueue; class GPUCommon : public GPUThreadEventQueue