From 3980638612f0ae781b890bc4614e65c3660c34f2 Mon Sep 17 00:00:00 2001 From: PoroCYon Date: Wed, 9 Sep 2020 17:01:42 +0200 Subject: [PATCH] Use std::atomic instead of the windows-only primitives for atomic operations in the song renderer --- WaveSabreCore/CMakeLists.txt | 12 +++++- WaveSabrePlayerLib/CMakeLists.txt | 4 ++ .../WaveSabrePlayerLib/AtomicHelpers.h | 40 +++++++++++++++++++ WaveSabrePlayerLib/src/SongRenderer.cpp | 5 ++- 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 WaveSabrePlayerLib/include/WaveSabrePlayerLib/AtomicHelpers.h diff --git a/WaveSabreCore/CMakeLists.txt b/WaveSabreCore/CMakeLists.txt index 31ca1e2e..d5b12291 100644 --- a/WaveSabreCore/CMakeLists.txt +++ b/WaveSabreCore/CMakeLists.txt @@ -54,7 +54,8 @@ add_library(WaveSabreCore src/Thunder.cpp src/Twister.cpp) -target_link_libraries(WaveSabreCore Msacm32.lib) +target_link_libraries(WaveSabreCore PUBLIC Msacm32.lib) + target_include_directories(WaveSabreCore PUBLIC include) if(MSVC) @@ -69,4 +70,13 @@ if(MSVC) target_compile_options(WaveSabreCore PUBLIC $<$:/Zc:sizedDealloc->) endif() +else() + # assuming GCC or clang for now + + if(CMAKE_BUILD_TYPE NOTEQUAL Debug) + set_property(TARGET WaveSabreCore PROPERTY INTERPROCEDURAL_OPTIMIZATION ON) + target_compile_options(WaveSabreCore + PUBLIC $<$:-Os -fno-exceptions -fno-rtti -fno-stack-protector -fno-stack-check -fno-unwind-tables -fno-asynchronous-unwind-tables -fomit-frame-pointer -fno-threadsafe-statics> + PRIVATE $<$:-fno-math-errno -march=nocona -ffunction-sections -fdata-sections -Wl,--gc-sections) + endif() endif() diff --git a/WaveSabrePlayerLib/CMakeLists.txt b/WaveSabrePlayerLib/CMakeLists.txt index 6a0149d4..75a5b2fe 100644 --- a/WaveSabrePlayerLib/CMakeLists.txt +++ b/WaveSabrePlayerLib/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(WaveSabrePlayerLib + include/WaveSabrePlayerLib/AtomicHelpers.h include/WaveSabrePlayerLib/CriticalSection.h include/WaveSabrePlayerLib/PreRenderPlayer.h include/WaveSabrePlayerLib/WavWriter.h @@ -28,4 +29,7 @@ if(MSVC) $<$:/EHs-c->) set_property(TARGET WaveSabrePlayerLib APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS_MINSIZEREL " /LTCG") +else() + # we need C++11 for std::atomic + set_property(TARGET WaveSabrePlayerLib PROPERTY CXX_STANDARD 11) endif() diff --git a/WaveSabrePlayerLib/include/WaveSabrePlayerLib/AtomicHelpers.h b/WaveSabrePlayerLib/include/WaveSabrePlayerLib/AtomicHelpers.h new file mode 100644 index 00000000..f3d20ab0 --- /dev/null +++ b/WaveSabrePlayerLib/include/WaveSabrePlayerLib/AtomicHelpers.h @@ -0,0 +1,40 @@ +#ifndef __WAVESABREPLAYERLIB_ATOMIC_HELPERS_H__ +#define __WAVESABREPLAYERLIB_ATOMIC_HELPERS_H__ + +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace WaveSabreCore +{ + namespace AtomicHelpers + { + template + inline bool CmpXchg(T* value, T newval, T expect) + { +#ifdef _WIN32 + return InterlockedCompareExchange((unsigned int*)value, + (unsigned int)newval, (unsigned int)expect) + == (unsigned int)expect; +#else + return std::atomic_compare_exchange_strong((std::atomic_int*)value, + (int*)&expect, newval); +#endif + } + + template + inline T XDec(T* value) + { +#ifdef _WIN32 + return (T)InterlockedDecrement((unsigned int*)value); +#else + // returns the value *before* the call + return (T)(std::atomic_fetch_sub((std::atomic_int*)value, 1) - 1); +#endif + } + } +} + +#endif diff --git a/WaveSabrePlayerLib/src/SongRenderer.cpp b/WaveSabrePlayerLib/src/SongRenderer.cpp index 4923ac72..4c50f4ba 100644 --- a/WaveSabrePlayerLib/src/SongRenderer.cpp +++ b/WaveSabrePlayerLib/src/SongRenderer.cpp @@ -1,3 +1,4 @@ +#include #include using namespace WaveSabreCore; @@ -195,7 +196,7 @@ namespace WaveSabrePlayerLib // We have a free track that we can work on, yay! // Let's try to mark it so that no other thread takes it - if ((TrackRenderState)InterlockedCompareExchange((unsigned int *)&trackRenderStates[i], (unsigned int)TrackRenderState::Rendering, (unsigned int)TrackRenderState::Idle) == TrackRenderState::Idle) + if (AtomicHelpers::CmpXchg(&trackRenderStates[i], TrackRenderState::Rendering, TrackRenderState::Idle)) { // We marked it successfully, so now we'll do the work tracks[i]->Run(renderThreadNumFloatSamples); @@ -206,7 +207,7 @@ namespace WaveSabrePlayerLib } } - if (!InterlockedDecrement(&renderThreadsRunning)) + if (AtomicHelpers::XDec(&renderThreadsRunning) == 0) SetEvent(renderDoneEvent); return true;