mirror of
https://github.com/PCSX2/pcsx2.git
synced 2024-10-07 15:33:29 +00:00
13dfceff48
* common: format AlignedMalloc.cpp * common: format AppTrait.h * common: format Assertions.h * common: format CheckedStaticBox * common: format Console * common: format Dependencies.h * common: format EmbeddedImage * common: format EventSource * common: format Exceptions * common: format FastFormatString.cpp * common: format General.h * common: format InitInterface * common: format MathUtils.h * common: format MemsetFast/MemcpyFast * common: format Mutex.cpp * common: format PageFaultSource.h * common: format Path.h * common: format PathUtils.cpp * common: format Pcsx2Types.h * common: format Perf * common: format PersistentThread.h * common: format RwMutex * common: format SafeArray * common: format ScopedAlloc.h * common: format ScopedPtrMT.h * common: format Semaphore.cpp * common: format StringHelpers * common: format ThreadTools.cpp * common: format Threading.h * common: format ThreadingDialogs * common: format ThreadingInternal.h * common: format TraceLog.h * common: format VirtualMemory.cpp * common: format pxCheckBox * common: format pxEvents.h * common: format pxForwardDefs.h * common: format pxRadioPanel * common: format pxStaticText * common: format pxStreams * common: format pxTranslate.cpp * common: format pxWindowTextWriter.cpp * common: format wxAppWithHelpers * common: format wxBaseTools.h * common: format wxGuiTools * common: format wxHelpers.cpp * common: format Darwin directory * common: format Linux directory * common: format Windows directory * common: format LnxCpuDetect.cpp * common: format WinCpuDetect.cpp * common: format bmi.cpp * common: format cpudetect.cpp * common: format cpu_detect_internal.h * common: format fpu.cpp * common: format groups.cpp * common: format instructions.h * common: format internal.h * common: format jmp.cpp * common: format legacy.cpp * common: format legacy_instructions.h * common: format legacy_internal.h * common: format movs.cpp * common: format simd.cpp * common: format tools.h * common: format x86emitter.cpp * common: format x86types.h * common: format bmi.h * common: format dwshift.h * common: format group1.h group2.h group3.h * common: format incdec.h * common: format jmpcall.h * common: format movs.h * common: format simd_arithmetic.h * common: format simd_comparisons.h * common: format simd_helpers.h * common: format simd_moremovs.h * common: format simd_shufflepack.h * common: format simd_templated_helpers.h * common: format test.h
210 lines
8.0 KiB
C++
210 lines
8.0 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
*
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* PCSX2 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "common/Threading.h"
|
|
#include "common/ScopedPtrMT.h"
|
|
#include "common/EventSource.h"
|
|
|
|
namespace Threading
|
|
{
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// ThreadDeleteEvent
|
|
// --------------------------------------------------------------------------------------
|
|
class EventListener_Thread : public IEventDispatcher<int>
|
|
{
|
|
public:
|
|
typedef int EvtParams;
|
|
|
|
protected:
|
|
pxThread* m_thread;
|
|
|
|
public:
|
|
EventListener_Thread()
|
|
{
|
|
m_thread = NULL;
|
|
}
|
|
|
|
virtual ~EventListener_Thread() = default;
|
|
|
|
void SetThread(pxThread& thr) { m_thread = &thr; }
|
|
void SetThread(pxThread* thr) { m_thread = thr; }
|
|
|
|
void DispatchEvent(const int& params)
|
|
{
|
|
OnThreadCleanup();
|
|
}
|
|
|
|
protected:
|
|
// Invoked by the pxThread when the thread execution is ending. This is
|
|
// typically more useful than a delete listener since the extended thread information
|
|
// provided by virtualized functions/methods will be available.
|
|
// Important! This event is executed *by the thread*, so care must be taken to ensure
|
|
// thread sync when necessary (posting messages to the main thread, etc).
|
|
virtual void OnThreadCleanup() = 0;
|
|
};
|
|
|
|
/// Set the name of the current thread
|
|
void SetNameOfCurrentThread(const char* name);
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// pxThread - Helper class for the basics of starting/managing persistent threads.
|
|
// --------------------------------------------------------------------------------------
|
|
// This class is meant to be a helper for the typical threading model of "start once and
|
|
// reuse many times." This class incorporates a lot of extra overhead in stopping and
|
|
// starting threads, but in turn provides most of the basic thread-safety and event-handling
|
|
// functionality needed for a threaded operation. In practice this model is usually an
|
|
// ideal one for efficiency since Operating Systems themselves typically subscribe to a
|
|
// design where sleeping, suspending, and resuming threads is very efficient, but starting
|
|
// new threads has quite a bit of overhead.
|
|
//
|
|
// To use this as a base class for your threaded procedure, overload the following virtual
|
|
// methods:
|
|
// void OnStart();
|
|
// void ExecuteTaskInThread();
|
|
// void OnCleanupInThread();
|
|
//
|
|
// Use the public methods Start() and Cancel() to start and shutdown the thread, and use
|
|
// m_sem_event internally to post/receive events for the thread (make a public accessor for
|
|
// it in your derived class if your thread utilizes the post).
|
|
//
|
|
// Notes:
|
|
// * Constructing threads as static global vars isn't recommended since it can potentially
|
|
// confuse w32pthreads, if the static initializers are executed out-of-order (C++ offers
|
|
// no dependency options for ensuring correct static var initializations). Use heap
|
|
// allocation to create thread objects instead.
|
|
//
|
|
class pxThread
|
|
{
|
|
DeclareNoncopyableObject(pxThread);
|
|
|
|
friend void pxYield(int ms);
|
|
|
|
protected:
|
|
wxString m_name; // diagnostic name for our thread.
|
|
pthread_t m_thread;
|
|
uptr m_native_id; // typically an id, but implementing platforms can do whatever.
|
|
uptr m_native_handle; // typically a pointer/handle, but implementing platforms can do whatever.
|
|
|
|
Semaphore m_sem_event; // general wait event that's needed by most threads
|
|
Semaphore m_sem_startup; // startup sync tool
|
|
Mutex m_mtx_InThread; // used for canceling and closing threads in a deadlock-safe manner
|
|
MutexRecursive m_mtx_start; // used to lock the Start() code from starting simultaneous threads accidentally.
|
|
Mutex m_mtx_ThreadName;
|
|
|
|
std::atomic<bool> m_detached; // a boolean value which indicates if the m_thread handle is valid
|
|
std::atomic<bool> m_running; // set true by Start(), and set false by Cancel(), Block(), etc.
|
|
|
|
// exception handle, set non-NULL if the thread terminated with an exception
|
|
// Use RethrowException() to re-throw the exception using its original exception type.
|
|
ScopedPtrMT<BaseException> m_except;
|
|
|
|
EventSource<EventListener_Thread> m_evtsrc_OnDelete;
|
|
|
|
|
|
public:
|
|
virtual ~pxThread();
|
|
pxThread(const wxString& name = L"pxThread");
|
|
|
|
pthread_t GetId() const { return m_thread; }
|
|
u64 GetCpuTime() const;
|
|
|
|
virtual void Start();
|
|
virtual void Cancel(bool isBlocking = true);
|
|
virtual bool Cancel(const wxTimeSpan& timeout);
|
|
virtual bool Detach();
|
|
virtual void Block();
|
|
virtual bool Block(const wxTimeSpan& timeout);
|
|
virtual void RethrowException() const;
|
|
|
|
void AddListener(EventListener_Thread& evt);
|
|
void AddListener(EventListener_Thread* evt)
|
|
{
|
|
if (evt == NULL)
|
|
return;
|
|
AddListener(*evt);
|
|
}
|
|
|
|
void WaitOnSelf(Semaphore& mutex) const;
|
|
void WaitOnSelf(Mutex& mutex) const;
|
|
bool WaitOnSelf(Semaphore& mutex, const wxTimeSpan& timeout) const;
|
|
bool WaitOnSelf(Mutex& mutex, const wxTimeSpan& timeout) const;
|
|
|
|
bool IsRunning() const;
|
|
bool IsSelf() const;
|
|
bool HasPendingException() const { return !!m_except; }
|
|
|
|
wxString GetName() const;
|
|
void SetName(const wxString& newname);
|
|
|
|
protected:
|
|
// Extending classes should always implement your own OnStart(), which is called by
|
|
// Start() once necessary locks have been obtained. Do not override Start() directly
|
|
// unless you're really sure that's what you need to do. ;)
|
|
virtual void OnStart();
|
|
|
|
virtual void OnStartInThread();
|
|
|
|
// This is called when the thread has been canceled or exits normally. The pxThread
|
|
// automatically binds it to the pthread cleanup routines as soon as the thread starts.
|
|
virtual void OnCleanupInThread();
|
|
|
|
// Implemented by derived class to perform actual threaded task!
|
|
virtual void ExecuteTaskInThread() = 0;
|
|
|
|
void TestCancel() const;
|
|
|
|
// Yields this thread to other threads and checks for cancellation. A sleeping thread should
|
|
// always test for cancellation, however if you really don't want to, you can use Threading::Sleep()
|
|
// or better yet, disable cancellation of the thread completely with DisableCancellation().
|
|
//
|
|
// Parameters:
|
|
// ms - 'minimum' yield time in milliseconds (rough -- typically yields are longer by 1-5ms
|
|
// depending on operating system/platform). If ms is 0 or unspecified, then a single
|
|
// timeslice is yielded to other contending threads. If no threads are contending for
|
|
// time when ms==0, then no yield is done, but cancellation is still tested.
|
|
void Yield(int ms = 0)
|
|
{
|
|
pxAssert(IsSelf());
|
|
Threading::Sleep(ms);
|
|
TestCancel();
|
|
}
|
|
|
|
void FrankenMutex(Mutex& mutex);
|
|
|
|
bool AffinityAssert_AllowFromSelf(const DiagnosticOrigin& origin) const;
|
|
bool AffinityAssert_DisallowFromSelf(const DiagnosticOrigin& origin) const;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Section of methods for internal use only.
|
|
|
|
void _platform_specific_OnStartInThread();
|
|
void _platform_specific_OnCleanupInThread();
|
|
bool _basecancel();
|
|
void _selfRunningTest(const wxChar* name) const;
|
|
void _DoSetThreadName(const wxString& name);
|
|
void _DoSetThreadName(const char* name) { SetNameOfCurrentThread(name); }
|
|
void _internal_execute();
|
|
void _try_virtual_invoke(void (pxThread::*method)());
|
|
void _ThreadCleanup();
|
|
|
|
static void* _internal_callback(void* func);
|
|
static void internal_callback_helper(void* func);
|
|
static void _pt_callback_cleanup(void* handle);
|
|
};
|
|
} // namespace Threading
|