diff --git a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h index 09f4cb31f43..a83a437c7b6 100644 --- a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h +++ b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h @@ -24,6 +24,7 @@ #include "Common/GameAudio.h" #include "mss/mss.h" #include "WWLib/mutex.h" +#include "Utility/atomic_adapter.h" class AudioEventRTS; class DynamicAudioEventRTS; @@ -65,7 +66,7 @@ struct PlayingAudio RefCountPtr m_audioEventRTS; void *m_file; // The file that was opened to play this PlayingAudioType m_type; - volatile PlayingStatus m_status; // This member is adjusted by another running thread. + std::atomic m_status; // This member is adjusted by another running thread. Short m_framesFaded; Bool m_fade; volatile Bool m_rerequestOnNextUpdate; @@ -92,8 +93,6 @@ struct PlayingAudio { return m_status == PS_Playing || m_rerequestOnNextUpdate; } - - static_assert(sizeof(m_status) == sizeof(long), "Must be size of long, because it is used with Interlocked functions"); }; struct ProviderInfo diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 97be26ca5a4..7a3390618fb 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -1074,13 +1074,21 @@ void MilesAudioManager::releasePlayingAudio( PlayingAudio *playing ) delete playing; } +//------------------------------------------------------------------------------------------------- +// Sets the status to 'to' if it is 'from', in one atomic step, and returns the status it had before. +static PlayingStatus advancePlayingStatus( PlayingAudio* playing, PlayingStatus from, PlayingStatus to ) +{ + playing->m_status.compare_exchange_strong(from, to); + return from; +} + //------------------------------------------------------------------------------------------------- void MilesAudioManager::stopPlayingAudio( PlayingAudio *playing ) { // Advance from Playing to Stopping - InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopping, PS_Playing); + advancePlayingStatus(playing, PS_Playing, PS_Stopping); // Advance from Stopping to Stopped - const long prevStatus = InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopped, PS_Stopping); + const PlayingStatus prevStatus = advancePlayingStatus(playing, PS_Stopping, PS_Stopped); if (prevStatus != PS_Stopping) { return; } @@ -1597,7 +1605,7 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt handle, UnsignedInt } // it will be cleaned up on the next frame update - InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopping, PS_Playing); + advancePlayingStatus(playing, PS_Playing, PS_Stopping); } //------------------------------------------------------------------------------------------------- @@ -2740,7 +2748,7 @@ Bool MilesAudioManager::startNextLoop( PlayingAudio *playing ) if (playing->m_audioEventRTS->getDelay() > MSEC_PER_LOGICFRAME_REAL) { playing->m_rerequestOnNextUpdate = true; - InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopping, PS_Playing); + advancePlayingStatus(playing, PS_Playing, PS_Stopping); return true; } diff --git a/Core/Libraries/Source/WWVegas/WWLib/mpsc_intrusive_queue.h b/Core/Libraries/Source/WWVegas/WWLib/mpsc_intrusive_queue.h index 7c2b92a5cf2..dbdc3d58a54 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/mpsc_intrusive_queue.h +++ b/Core/Libraries/Source/WWVegas/WWLib/mpsc_intrusive_queue.h @@ -18,7 +18,7 @@ #pragma once -#include "Utility/interlocked_adapter.h" +#include "Utility/atomic_adapter.h" // Lock-free intrusive queue for multiple producer threads and a single consumer thread, // using the same algorithm as the Win32 InterlockedPushEntrySList/InterlockedFlushSList @@ -38,14 +38,12 @@ class MPSCIntrusiveQueue // head, so its next pointer is never visible while stale. void Push(T* node) { - T* head; + T* head = m_head.load(); do { - head = m_head; node->next = head; } - while (InterlockedCompareExchangePointer( - reinterpret_cast(&m_head), node, head) != head); + while (!m_head.compare_exchange_weak(head, node)); } // Detaches all nodes and returns them linked in push order, or null if the queue is @@ -54,8 +52,7 @@ class MPSCIntrusiveQueue // suffer ABA. T* Flush() { - T* list = static_cast(InterlockedExchangePointer( - reinterpret_cast(&m_head), nullptr)); + T* list = m_head.exchange(nullptr); // The detached chain is in last-in-first-out order, so reverse it. T* reversed = nullptr; @@ -73,5 +70,5 @@ class MPSCIntrusiveQueue MPSCIntrusiveQueue(const MPSCIntrusiveQueue&) CPP_11(= delete); MPSCIntrusiveQueue& operator=(const MPSCIntrusiveQueue&) CPP_11(= delete); - T* volatile m_head; + std::atomic m_head; };