common: port ScopedPtrMT to std::atomic

v2: s/NULL/nullptr/
v3: tentative fix for MSVC
// ScopedPtrMT.h(91, 0): error C2593: 'operator ==' is ambiguous
This commit is contained in:
Gregory Hainaut 2016-02-22 19:36:45 +01:00
parent cb776d2f50
commit 89fad4d3ad
4 changed files with 17 additions and 44 deletions

View File

@ -200,6 +200,7 @@ public:
#include <list> #include <list>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <atomic>
#include "Pcsx2Defs.h" #include "Pcsx2Defs.h"

View File

@ -27,25 +27,23 @@ class ScopedPtrMT
{ {
DeclareNoncopyableObject(ScopedPtrMT); DeclareNoncopyableObject(ScopedPtrMT);
typedef T* TPtr;
protected: protected:
volatile TPtr m_ptr; std::atomic<T*> m_ptr;
Threading::Mutex m_mtx; Threading::Mutex m_mtx;
public: public:
typedef T element_type; typedef T element_type;
wxEXPLICIT ScopedPtrMT(T * ptr = NULL) wxEXPLICIT ScopedPtrMT(T * ptr = nullptr)
{ {
m_ptr = ptr; m_ptr = ptr;
} }
~ScopedPtrMT() throw() { _Delete_unlocked(); } ~ScopedPtrMT() throw() { _Delete_unlocked(); }
ScopedPtrMT& Reassign(T * ptr = NULL) ScopedPtrMT& Reassign(T * ptr = nullptr)
{ {
TPtr doh = (TPtr)Threading::AtomicExchangePointer( m_ptr, ptr ); T* doh = m_ptr.exchange(ptr);
if ( ptr != doh ) delete doh; if ( ptr != doh ) delete doh;
return *this; return *this;
} }
@ -57,17 +55,15 @@ public:
} }
// Removes the pointer from scoped management, but does not delete! // Removes the pointer from scoped management, but does not delete!
// (ScopedPtr will be NULL after this method) // (ScopedPtr will be nullptr after this method)
T *DetachPtr() T *DetachPtr()
{ {
ScopedLock lock( m_mtx ); ScopedLock lock( m_mtx );
T *ptr = m_ptr; return m_ptr.exchange(nullptr);
m_ptr = NULL;
return ptr;
} }
// Returns the managed pointer. Can return NULL as a valid result if the ScopedPtrMT // Returns the managed pointer. Can return nullptr as a valid result if the ScopedPtrMT
// has no object in management. // has no object in management.
T* GetPtr() const T* GetPtr() const
{ {
@ -77,6 +73,7 @@ public:
void SwapPtr(ScopedPtrMT& other) void SwapPtr(ScopedPtrMT& other)
{ {
ScopedLock lock( m_mtx ); ScopedLock lock( m_mtx );
m_ptr.exchange(other.m_ptr.exchange(m_ptr.load()));
T * const tmp = other.m_ptr; T * const tmp = other.m_ptr;
other.m_ptr = m_ptr; other.m_ptr = m_ptr;
m_ptr = tmp; m_ptr = tmp;
@ -91,7 +88,7 @@ public:
bool operator!() const throw() bool operator!() const throw()
{ {
return m_ptr == NULL; return m_ptr.load() == nullptr;
} }
// Equality // Equality
@ -106,7 +103,7 @@ public:
return !operator==(pT); return !operator==(pT);
} }
// Convenient assignment operator. ScopedPtrMT = NULL will issue an automatic deletion // Convenient assignment operator. ScopedPtrMT = nullptr will issue an automatic deletion
// of the managed pointer. // of the managed pointer.
ScopedPtrMT& operator=( T* src ) ScopedPtrMT& operator=( T* src )
{ {
@ -120,16 +117,16 @@ public:
} }
// Dereference operator, returns a handle to the managed pointer. // Dereference operator, returns a handle to the managed pointer.
// Generates a debug assertion if the object is NULL! // Generates a debug assertion if the object is nullptr!
T& operator*() const T& operator*() const
{ {
pxAssert(m_ptr != NULL); pxAssert(m_ptr != nullptr);
return *m_ptr; return *m_ptr;
} }
T* operator->() const T* operator->() const
{ {
pxAssert(m_ptr != NULL); pxAssert(m_ptr != nullptr);
return m_ptr; return m_ptr;
} }
#endif #endif
@ -137,7 +134,6 @@ public:
protected: protected:
void _Delete_unlocked() throw() void _Delete_unlocked() throw()
{ {
delete m_ptr; delete m_ptr.exchange(nullptr);
m_ptr = NULL;
} }
}; };

View File

@ -192,12 +192,6 @@ namespace Threading
extern bool AtomicBitTestAndReset( volatile u32& bitset, u8 bit ); extern bool AtomicBitTestAndReset( volatile u32& bitset, u8 bit );
extern bool AtomicBitTestAndReset( volatile s32& bitset, u8 bit ); extern bool AtomicBitTestAndReset( volatile s32& bitset, u8 bit );
extern void* _AtomicExchangePointer( volatile uptr& target, uptr value );
extern void* _AtomicCompareExchangePointer( volatile uptr& target, uptr value, uptr comparand );
#define AtomicExchangePointer( dest, src ) _AtomicExchangePointer( (uptr&)dest, (uptr)src )
#define AtomicCompareExchangePointer( dest, comp, src ) _AtomicExchangePointer( (uptr&)dest, (uptr)comp, (uptr)src )
// pthread Cond is an evil api that is not suited for Pcsx2 needs. // pthread Cond is an evil api that is not suited for Pcsx2 needs.
// Let's not use it. Use mutexes and semaphores instead to create waits. (Air) // Let's not use it. Use mutexes and semaphores instead to create waits. (Air)
#if 0 #if 0

View File

@ -828,24 +828,6 @@ __fi s32 Threading::AtomicDecrement(volatile s32& Target) {
return _InterlockedExchangeAdd((volatile vol_t*)&Target, -1); return _InterlockedExchangeAdd((volatile vol_t*)&Target, -1);
} }
__fi void* Threading::_AtomicExchangePointer(volatile uptr& target, uptr value)
{
#ifdef _M_X86_64 // high-level atomic ops, please leave these 64 bit checks in place.
return (void*)_InterlockedExchange64((volatile s64*)&target, value);
#else
return (void*)_InterlockedExchange((volatile vol_t*)&target, value);
#endif
}
__fi void* Threading::_AtomicCompareExchangePointer(volatile uptr& target, uptr value, uptr comparand)
{
#ifdef _M_X86_64 // high-level atomic ops, please leave these 64 bit checks in place.
return (void*)_InterlockedCompareExchange64((volatile s64*)&target, value, comparand);
#else
return (void*)_InterlockedCompareExchange((volatile vol_t*)&target, value, comparand);
#endif
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// BaseThreadError // BaseThreadError
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------