mirror of https://github.com/PCSX2/pcsx2.git
Common/Threading: Move a bunch of unnecessary wrappers to gui
This commit is contained in:
parent
65e956a01c
commit
e5716922a3
|
@ -20,7 +20,6 @@ target_sources(common PRIVATE
|
|||
FastFormatString.cpp
|
||||
FastJmp.cpp
|
||||
FileSystem.cpp
|
||||
Mutex.cpp
|
||||
Misc.cpp
|
||||
MD5Digest.cpp
|
||||
PathUtils.cpp
|
||||
|
@ -33,7 +32,6 @@ target_sources(common PRIVATE
|
|||
StringHelpers.cpp
|
||||
StringUtil.cpp
|
||||
Timer.cpp
|
||||
ThreadTools.cpp
|
||||
WindowInfo.cpp
|
||||
emitter/bmi.cpp
|
||||
emitter/cpudetect.cpp
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/thread_act.h>
|
||||
|
@ -32,6 +33,11 @@ __forceinline void Threading::Sleep(int ms)
|
|||
usleep(1000 * ms);
|
||||
}
|
||||
|
||||
__forceinline void Threading::Timeslice()
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
// For use in spin/wait loops, acts as a hint to Intel CPUs and should, in theory
|
||||
// improve performance and reduce cpu power consumption.
|
||||
__forceinline void Threading::SpinWait()
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "common/Dependencies.h" // _ macro
|
||||
#include "common/Threading.h"
|
||||
#include "common/General.h"
|
||||
#include "common/StringHelpers.h"
|
||||
|
||||
// for lack of a better place...
|
||||
Fnptr_OutOfMemory pxDoOutOfMemory = NULL;
|
||||
|
|
|
@ -55,6 +55,11 @@ __forceinline void Threading::Sleep(int ms)
|
|||
usleep(1000 * ms);
|
||||
}
|
||||
|
||||
__forceinline void Threading::Timeslice()
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
// For use in spin/wait loops, Acts as a hint to Intel CPUs and should, in theory
|
||||
// improve performance and reduce cpu power consumption.
|
||||
__forceinline void Threading::SpinWait()
|
||||
|
|
|
@ -14,11 +14,14 @@
|
|||
*/
|
||||
|
||||
#include "common/Threading.h"
|
||||
#include "common/Assertions.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "common/RedtapeWindows.h"
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Semaphore Implementations
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -168,4 +171,4 @@ bool Threading::KernelSemaphore::TryWait()
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "common/Threading.h"
|
||||
|
||||
void Threading::pxTestCancel()
|
||||
{
|
||||
pthread_testcancel();
|
||||
}
|
||||
|
||||
__fi void Threading::Timeslice()
|
||||
{
|
||||
sched_yield();
|
||||
}
|
|
@ -15,21 +15,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <wx/datetime.h>
|
||||
#ifdef _WIN32
|
||||
// thanks I hate it.
|
||||
#include <wx/filefn.h>
|
||||
#define HAVE_MODE_T
|
||||
#endif
|
||||
#include <semaphore.h>
|
||||
#include <errno.h> // EBUSY
|
||||
#include <pthread.h>
|
||||
#ifdef __APPLE__
|
||||
#include <mach/semaphore.h>
|
||||
#endif
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/TraceLog.h"
|
||||
#include "common/General.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/semaphore.h>
|
||||
#elif !defined(_WIN32)
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -52,12 +46,11 @@
|
|||
|
||||
namespace Threading
|
||||
{
|
||||
class ThreadHandle;
|
||||
class pxThread;
|
||||
class RwMutex;
|
||||
|
||||
extern void pxTestCancel();
|
||||
extern void YieldToMain();
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Platform Specific External APIs
|
||||
// --------------------------------------------------------------------------------------
|
||||
// The following set of documented functions have Linux/Win32 specific implementations,
|
||||
// which are found in WinThreads.cpp and LnxThreads.cpp
|
||||
|
||||
extern u64 GetThreadCpuTime();
|
||||
extern u64 GetThreadTicksPerSecond();
|
||||
|
@ -65,17 +58,6 @@ namespace Threading
|
|||
/// Set the name of the current thread
|
||||
extern void SetNameOfCurrentThread(const char* name);
|
||||
|
||||
extern const wxTimeSpan def_yieldgui_interval;
|
||||
} // namespace Threading
|
||||
|
||||
namespace Threading
|
||||
{
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Platform Specific External APIs
|
||||
// --------------------------------------------------------------------------------------
|
||||
// The following set of documented functions have Linux/Win32 specific implementations,
|
||||
// which are found in WinThreads.cpp and LnxThreads.cpp
|
||||
|
||||
// Releases a timeslice to other threads.
|
||||
extern void Timeslice();
|
||||
|
||||
|
@ -129,44 +111,6 @@ namespace Threading
|
|||
#endif
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// NonblockingMutex
|
||||
// --------------------------------------------------------------------------------------
|
||||
// This is a very simple non-blocking mutex, which behaves similarly to pthread_mutex's
|
||||
// trylock(), but without any of the extra overhead needed to set up a structure capable
|
||||
// of blocking waits. It basically optimizes to a single InterlockedExchange.
|
||||
//
|
||||
// Simple use: if TryAcquire() returns false, the Bool is already interlocked by another thread.
|
||||
// If TryAcquire() returns true, you've locked the object and are *responsible* for unlocking
|
||||
// it later.
|
||||
//
|
||||
class NonblockingMutex
|
||||
{
|
||||
protected:
|
||||
std::atomic_flag val;
|
||||
|
||||
public:
|
||||
NonblockingMutex() { val.clear(); }
|
||||
virtual ~NonblockingMutex() = default;
|
||||
|
||||
bool TryAcquire() noexcept
|
||||
{
|
||||
return !val.test_and_set();
|
||||
}
|
||||
|
||||
// Can be done with a TryAcquire/Release but it is likely better to do it outside of the object
|
||||
bool IsLocked()
|
||||
{
|
||||
pxAssertMsg(0, "IsLocked isn't supported for NonblockingMutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
val.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/// A semaphore that may not have a fast userspace path
|
||||
/// (Used in other semaphore-based algorithms where the semaphore is just used for its thread sleep/wake ability)
|
||||
class KernelSemaphore
|
||||
|
@ -261,92 +205,4 @@ namespace Threading
|
|||
/// Should be called by the worker thread if it restarts after dying
|
||||
void Reset();
|
||||
};
|
||||
|
||||
class Mutex
|
||||
{
|
||||
protected:
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
virtual ~Mutex();
|
||||
virtual bool IsRecursive() const { return false; }
|
||||
|
||||
void Recreate();
|
||||
bool RecreateIfLocked();
|
||||
void Detach();
|
||||
|
||||
void Acquire();
|
||||
bool Acquire(const wxTimeSpan& timeout);
|
||||
bool TryAcquire();
|
||||
void Release();
|
||||
|
||||
void AcquireWithoutYield();
|
||||
bool AcquireWithoutYield(const wxTimeSpan& timeout);
|
||||
|
||||
void Wait();
|
||||
void WaitWithSpin();
|
||||
bool Wait(const wxTimeSpan& timeout);
|
||||
void WaitWithoutYield();
|
||||
bool WaitWithoutYield(const wxTimeSpan& timeout);
|
||||
|
||||
protected:
|
||||
// empty constructor used by MutexLockRecursive
|
||||
Mutex(bool) {}
|
||||
};
|
||||
|
||||
class MutexRecursive : public Mutex
|
||||
{
|
||||
public:
|
||||
MutexRecursive();
|
||||
virtual ~MutexRecursive();
|
||||
virtual bool IsRecursive() const { return true; }
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedLock
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Helper class for using Mutexes. Using this class provides an exception-safe (and
|
||||
// generally clean) method of locking code inside a function or conditional block. The lock
|
||||
// will be automatically released on any return or exit from the function.
|
||||
//
|
||||
// Const qualification note:
|
||||
// ScopedLock takes const instances of the mutex, even though the mutex is modified
|
||||
// by locking and unlocking. Two rationales:
|
||||
//
|
||||
// 1) when designing classes with accessors (GetString, GetValue, etc) that need mutexes,
|
||||
// this class needs a const hack to allow those accessors to be const (which is typically
|
||||
// *very* important).
|
||||
//
|
||||
// 2) The state of the Mutex is guaranteed to be unchanged when the calling function or
|
||||
// scope exits, by any means. Only via manual calls to Release or Acquire does that
|
||||
// change, and typically those are only used in very special circumstances of their own.
|
||||
//
|
||||
class ScopedLock
|
||||
{
|
||||
DeclareNoncopyableObject(ScopedLock);
|
||||
|
||||
protected:
|
||||
Mutex* m_lock;
|
||||
bool m_IsLocked;
|
||||
|
||||
public:
|
||||
virtual ~ScopedLock();
|
||||
explicit ScopedLock(const Mutex* locker = NULL);
|
||||
explicit ScopedLock(const Mutex& locker);
|
||||
void AssignAndLock(const Mutex& locker);
|
||||
void AssignAndLock(const Mutex* locker);
|
||||
|
||||
void Assign(const Mutex& locker);
|
||||
void Assign(const Mutex* locker);
|
||||
|
||||
void Release();
|
||||
void Acquire();
|
||||
|
||||
bool IsLocked() const { return m_IsLocked; }
|
||||
|
||||
protected:
|
||||
// Special constructor used by ScopedTryLock
|
||||
ScopedLock(const Mutex& locker, bool isTryLock);
|
||||
};
|
||||
} // namespace Threading
|
||||
|
|
|
@ -24,6 +24,11 @@ __fi void Threading::Sleep(int ms)
|
|||
::Sleep(ms);
|
||||
}
|
||||
|
||||
__fi void Threading::Timeslice()
|
||||
{
|
||||
::Sleep(0);
|
||||
}
|
||||
|
||||
// For use in spin/wait loops, Acts as a hint to Intel CPUs and should, in theory
|
||||
// improve performance and reduce cpu power consumption.
|
||||
__fi void Threading::SpinWait()
|
||||
|
|
|
@ -98,9 +98,7 @@
|
|||
<ClCompile Include="Windows\WinMisc.cpp" />
|
||||
<ClCompile Include="Windows\WinThreads.cpp" />
|
||||
<ClCompile Include="Misc.cpp" />
|
||||
<ClCompile Include="Mutex.cpp" />
|
||||
<ClCompile Include="Semaphore.cpp" />
|
||||
<ClCompile Include="ThreadTools.cpp" />
|
||||
<ClCompile Include="emitter\bmi.cpp" />
|
||||
<ClCompile Include="emitter\cpudetect.cpp" />
|
||||
<ClCompile Include="emitter\fpu.cpp" />
|
||||
|
|
|
@ -52,9 +52,6 @@
|
|||
<ClCompile Include="Misc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Mutex.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PathUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -76,9 +73,6 @@
|
|||
<ClCompile Include="StringHelpers.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ThreadTools.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VirtualMemory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
namespace x86Emitter
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
//------------------------------------------------------------------
|
||||
|
||||
#include "common/emitter/legacy_internal.h"
|
||||
#include "common/Console.h"
|
||||
|
||||
emitterT void ModRM(uint mod, uint reg, uint rm)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/Threading.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
static const uint iREGCNT_XMM = 16;
|
||||
static const uint iREGCNT_GPR = 16;
|
||||
|
|
|
@ -1119,6 +1119,7 @@ set(pcsx2GuiSources
|
|||
gui/MainFrame.cpp
|
||||
gui/MainMenuClicks.cpp
|
||||
gui/MessageBoxes.cpp
|
||||
gui/Mutex.cpp
|
||||
gui/MSWstuff.cpp
|
||||
gui/Panels/BaseApplicableConfigPanel.cpp
|
||||
gui/Panels/BiosSelectorPanel.cpp
|
||||
|
@ -1195,7 +1196,6 @@ set(pcsx2GuiHeaders
|
|||
gui/pxStaticText.h
|
||||
gui/RecentIsoList.h
|
||||
gui/Saveslots.h
|
||||
gui/ScopedPtrMT.h
|
||||
gui/SysThreads.h
|
||||
gui/ThreadingDialogs.h
|
||||
gui/ThreadingDialogs.cpp
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/Threading.h"
|
||||
#include "PersistentThread.h"
|
||||
|
||||
namespace Threading
|
||||
{
|
|
@ -17,7 +17,16 @@
|
|||
|
||||
#include "common/Threading.h"
|
||||
#include "common/EventSource.h"
|
||||
#include "ScopedPtrMT.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/TraceLog.h"
|
||||
#include <wx/datetime.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/semaphore.h>
|
||||
#else
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#undef Yield // release the burden of windows.h global namespace spam.
|
||||
|
||||
|
@ -113,12 +122,227 @@ namespace Exception
|
|||
|
||||
namespace Threading
|
||||
{
|
||||
extern void pxTestCancel();
|
||||
extern void YieldToMain();
|
||||
|
||||
extern const wxTimeSpan def_yieldgui_interval;
|
||||
|
||||
extern pxThread* pxGetCurrentThread();
|
||||
extern wxString pxGetCurrentThreadName();
|
||||
extern bool _WaitGui_RecursionGuard(const wxChar* name);
|
||||
|
||||
extern bool AllowDeletions();
|
||||
|
||||
class Mutex
|
||||
{
|
||||
protected:
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
virtual ~Mutex();
|
||||
virtual bool IsRecursive() const { return false; }
|
||||
|
||||
void Recreate();
|
||||
bool RecreateIfLocked();
|
||||
void Detach();
|
||||
|
||||
void Acquire();
|
||||
bool Acquire(const wxTimeSpan& timeout);
|
||||
bool TryAcquire();
|
||||
void Release();
|
||||
|
||||
void AcquireWithoutYield();
|
||||
bool AcquireWithoutYield(const wxTimeSpan& timeout);
|
||||
|
||||
void Wait();
|
||||
void WaitWithSpin();
|
||||
bool Wait(const wxTimeSpan& timeout);
|
||||
void WaitWithoutYield();
|
||||
bool WaitWithoutYield(const wxTimeSpan& timeout);
|
||||
|
||||
protected:
|
||||
// empty constructor used by MutexLockRecursive
|
||||
Mutex(bool) {}
|
||||
};
|
||||
|
||||
class MutexRecursive : public Mutex
|
||||
{
|
||||
public:
|
||||
MutexRecursive();
|
||||
virtual ~MutexRecursive();
|
||||
virtual bool IsRecursive() const { return true; }
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedLock
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Helper class for using Mutexes. Using this class provides an exception-safe (and
|
||||
// generally clean) method of locking code inside a function or conditional block. The lock
|
||||
// will be automatically released on any return or exit from the function.
|
||||
//
|
||||
// Const qualification note:
|
||||
// ScopedLock takes const instances of the mutex, even though the mutex is modified
|
||||
// by locking and unlocking. Two rationales:
|
||||
//
|
||||
// 1) when designing classes with accessors (GetString, GetValue, etc) that need mutexes,
|
||||
// this class needs a const hack to allow those accessors to be const (which is typically
|
||||
// *very* important).
|
||||
//
|
||||
// 2) The state of the Mutex is guaranteed to be unchanged when the calling function or
|
||||
// scope exits, by any means. Only via manual calls to Release or Acquire does that
|
||||
// change, and typically those are only used in very special circumstances of their own.
|
||||
//
|
||||
class ScopedLock
|
||||
{
|
||||
DeclareNoncopyableObject(ScopedLock);
|
||||
|
||||
protected:
|
||||
Mutex* m_lock;
|
||||
bool m_IsLocked;
|
||||
|
||||
public:
|
||||
virtual ~ScopedLock();
|
||||
explicit ScopedLock(const Mutex* locker = NULL);
|
||||
explicit ScopedLock(const Mutex& locker);
|
||||
void AssignAndLock(const Mutex& locker);
|
||||
void AssignAndLock(const Mutex* locker);
|
||||
|
||||
void Assign(const Mutex& locker);
|
||||
void Assign(const Mutex* locker);
|
||||
|
||||
void Release();
|
||||
void Acquire();
|
||||
|
||||
bool IsLocked() const { return m_IsLocked; }
|
||||
|
||||
protected:
|
||||
// Special constructor used by ScopedTryLock
|
||||
ScopedLock(const Mutex& locker, bool isTryLock);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedPtrMT
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class ScopedPtrMT
|
||||
{
|
||||
DeclareNoncopyableObject(ScopedPtrMT);
|
||||
|
||||
protected:
|
||||
std::atomic<T*> m_ptr;
|
||||
Threading::Mutex m_mtx;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
wxEXPLICIT ScopedPtrMT(T* ptr = nullptr)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
}
|
||||
|
||||
~ScopedPtrMT() { _Delete_unlocked(); }
|
||||
|
||||
ScopedPtrMT& Reassign(T* ptr = nullptr)
|
||||
{
|
||||
T* doh = m_ptr.exchange(ptr);
|
||||
if (ptr != doh)
|
||||
delete doh;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ScopedPtrMT& Delete() noexcept
|
||||
{
|
||||
ScopedLock lock(m_mtx);
|
||||
_Delete_unlocked();
|
||||
}
|
||||
|
||||
// Removes the pointer from scoped management, but does not delete!
|
||||
// (ScopedPtr will be nullptr after this method)
|
||||
T* DetachPtr()
|
||||
{
|
||||
ScopedLock lock(m_mtx);
|
||||
|
||||
return m_ptr.exchange(nullptr);
|
||||
}
|
||||
|
||||
// Returns the managed pointer. Can return nullptr as a valid result if the ScopedPtrMT
|
||||
// has no object in management.
|
||||
T* GetPtr() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
void SwapPtr(ScopedPtrMT& other)
|
||||
{
|
||||
ScopedLock lock(m_mtx);
|
||||
m_ptr.exchange(other.m_ptr.exchange(m_ptr.load()));
|
||||
T* const tmp = other.m_ptr;
|
||||
other.m_ptr = m_ptr;
|
||||
m_ptr = tmp;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ScopedPtrMT Operators
|
||||
// ----------------------------------------------------------------------------
|
||||
// I've decided to use the ATL's approach to pointer validity tests, opposed to
|
||||
// the wx/boost approach (which uses some bizarre member method pointer crap, and can't
|
||||
// allow the T* implicit casting.
|
||||
|
||||
bool operator!() const noexcept
|
||||
{
|
||||
return m_ptr.load() == nullptr;
|
||||
}
|
||||
|
||||
// Equality
|
||||
bool operator==(T* pT) const noexcept
|
||||
{
|
||||
return m_ptr == pT;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
bool operator!=(T* pT) const noexcept
|
||||
{
|
||||
return !operator==(pT);
|
||||
}
|
||||
|
||||
// Convenient assignment operator. ScopedPtrMT = nullptr will issue an automatic deletion
|
||||
// of the managed pointer.
|
||||
ScopedPtrMT& operator=(T* src)
|
||||
{
|
||||
return Reassign(src);
|
||||
}
|
||||
|
||||
#if 0
|
||||
operator T*() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
// Dereference operator, returns a handle to the managed pointer.
|
||||
// Generates a debug assertion if the object is nullptr!
|
||||
T& operator*() const
|
||||
{
|
||||
pxAssert(m_ptr != nullptr);
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
pxAssert(m_ptr != nullptr);
|
||||
return m_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void _Delete_unlocked() noexcept
|
||||
{
|
||||
delete m_ptr.exchange(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// RecursionGuard - Basic protection against function recursion
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
/* 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"
|
||||
using Threading::ScopedLock;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ScopedPtrMT
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class ScopedPtrMT
|
||||
{
|
||||
DeclareNoncopyableObject(ScopedPtrMT);
|
||||
|
||||
protected:
|
||||
std::atomic<T*> m_ptr;
|
||||
Threading::Mutex m_mtx;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
wxEXPLICIT ScopedPtrMT(T* ptr = nullptr)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
}
|
||||
|
||||
~ScopedPtrMT() { _Delete_unlocked(); }
|
||||
|
||||
ScopedPtrMT& Reassign(T* ptr = nullptr)
|
||||
{
|
||||
T* doh = m_ptr.exchange(ptr);
|
||||
if (ptr != doh)
|
||||
delete doh;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ScopedPtrMT& Delete() noexcept
|
||||
{
|
||||
ScopedLock lock(m_mtx);
|
||||
_Delete_unlocked();
|
||||
}
|
||||
|
||||
// Removes the pointer from scoped management, but does not delete!
|
||||
// (ScopedPtr will be nullptr after this method)
|
||||
T* DetachPtr()
|
||||
{
|
||||
ScopedLock lock(m_mtx);
|
||||
|
||||
return m_ptr.exchange(nullptr);
|
||||
}
|
||||
|
||||
// Returns the managed pointer. Can return nullptr as a valid result if the ScopedPtrMT
|
||||
// has no object in management.
|
||||
T* GetPtr() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
void SwapPtr(ScopedPtrMT& other)
|
||||
{
|
||||
ScopedLock lock(m_mtx);
|
||||
m_ptr.exchange(other.m_ptr.exchange(m_ptr.load()));
|
||||
T* const tmp = other.m_ptr;
|
||||
other.m_ptr = m_ptr;
|
||||
m_ptr = tmp;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ScopedPtrMT Operators
|
||||
// ----------------------------------------------------------------------------
|
||||
// I've decided to use the ATL's approach to pointer validity tests, opposed to
|
||||
// the wx/boost approach (which uses some bizarre member method pointer crap, and can't
|
||||
// allow the T* implicit casting.
|
||||
|
||||
bool operator!() const noexcept
|
||||
{
|
||||
return m_ptr.load() == nullptr;
|
||||
}
|
||||
|
||||
// Equality
|
||||
bool operator==(T* pT) const noexcept
|
||||
{
|
||||
return m_ptr == pT;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
bool operator!=(T* pT) const noexcept
|
||||
{
|
||||
return !operator==(pT);
|
||||
}
|
||||
|
||||
// Convenient assignment operator. ScopedPtrMT = nullptr will issue an automatic deletion
|
||||
// of the managed pointer.
|
||||
ScopedPtrMT& operator=(T* src)
|
||||
{
|
||||
return Reassign(src);
|
||||
}
|
||||
|
||||
#if 0
|
||||
operator T*() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
// Dereference operator, returns a handle to the managed pointer.
|
||||
// Generates a debug assertion if the object is nullptr!
|
||||
T& operator*() const
|
||||
{
|
||||
pxAssert(m_ptr != nullptr);
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
pxAssert(m_ptr != nullptr);
|
||||
return m_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void _Delete_unlocked() noexcept
|
||||
{
|
||||
delete m_ptr.exchange(nullptr);
|
||||
}
|
||||
};
|
|
@ -354,6 +354,7 @@
|
|||
<ClCompile Include="gui\Dialogs\McdConfigDialog.cpp" />
|
||||
<ClCompile Include="gui\DriveList.cpp" />
|
||||
<ClCompile Include="gui\IniInterface.cpp" />
|
||||
<ClCompile Include="gui\Mutex.cpp" />
|
||||
<ClCompile Include="gui\Panels\MemoryCardListView.cpp" />
|
||||
<ClCompile Include="gui\PersistentThread.cpp" />
|
||||
<ClCompile Include="gui\pxCheckBox.cpp" />
|
||||
|
@ -818,7 +819,6 @@
|
|||
<ClInclude Include="gui\Debugger\DebuggerLists.h" />
|
||||
<ClInclude Include="gui\Debugger\DisassemblyDialog.h" />
|
||||
<ClInclude Include="gui\Panels\MemoryCardPanels.h" />
|
||||
<ClInclude Include="gui\ScopedPtrMT.h" />
|
||||
<ClInclude Include="gui\ThreadingDialogs.h" />
|
||||
<ClInclude Include="gui\wxAppWithHelpers.h" />
|
||||
<ClInclude Include="gui\wxSettingsInterface.h" />
|
||||
|
|
|
@ -1769,7 +1769,12 @@
|
|||
<ClCompile Include="GS\Renderers\DX12\GSDevice12.cpp">
|
||||
<Filter>System\Ps2\GS\Renderers\Direct3D12</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gui\PersistentThread.cpp" />
|
||||
<ClCompile Include="gui\Mutex.cpp">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gui\PersistentThread.cpp">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Patch.h">
|
||||
|
@ -2946,8 +2951,9 @@
|
|||
<ClInclude Include="GS\Renderers\DX12\GSTexture12.h">
|
||||
<Filter>System\Ps2\GS\Renderers\Direct3D12</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gui\ScopedPtrMT.h" />
|
||||
<ClInclude Include="gui\PersistentThread.h" />
|
||||
<ClInclude Include="gui\PersistentThread.h">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="windows\wxResources.rc">
|
||||
|
|
Loading…
Reference in New Issue