From e06df7ae82814d248c2ae21da636af8126fc009f Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 7 May 2023 16:00:44 +0200 Subject: [PATCH] Make water atomic methods compatible with MSVC Signed-off-by: falkTX --- source/modules/water/common.hpp | 4 +- source/modules/water/memory/Atomic.h | 66 ++++++++++++++++++++++++++-- source/modules/water/water.obs.cpp | 2 +- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/source/modules/water/common.hpp b/source/modules/water/common.hpp index 73eab7b45..64f6e8f9f 100644 --- a/source/modules/water/common.hpp +++ b/source/modules/water/common.hpp @@ -1,7 +1,7 @@ /* * Cross-platform C++ library for Carla, based on Juce v4 * Copyright (C) 2015 ROLI Ltd. - * Copyright (C) 2017-2022 Filipe Coelho + * Copyright (C) 2017-2023 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -16,6 +16,8 @@ * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ +#pragma once + #include "maths/MathsFunctions.h" #include "misc/Result.h" diff --git a/source/modules/water/memory/Atomic.h b/source/modules/water/memory/Atomic.h index 41e08f427..cc03ef501 100644 --- a/source/modules/water/memory/Atomic.h +++ b/source/modules/water/memory/Atomic.h @@ -28,6 +28,15 @@ #include "../water.h" +#ifdef _MSC_VER +# ifndef NOMINMAX +# define NOMINMAX +# endif +# define WIN32_LEAN_AND_MEAN 1 +# include +# include +#endif + #include namespace water { @@ -161,7 +170,7 @@ public: #else __attribute__ ((aligned (4))) #endif - volatile Type value; + mutable volatile Type value; private: template @@ -171,8 +180,10 @@ private: static inline Type castFrom64Bit (int64 value) noexcept { return castTo (value); } static inline Type castFrom32Bit (uint32 value) noexcept { return castTo (value); } static inline Type castFrom64Bit (uint64 value) noexcept { return castTo (value); } + static inline Type castFromLong (long value) noexcept { return castTo (value); } static inline int32 castTo32Bit (Type value) noexcept { return castTo (value); } static inline int64 castTo64Bit (Type value) noexcept { return castTo (value); } + static inline long castToLong (Type value) noexcept { return castTo (value); } Type operator++ (int); // better to just use pre-increment with atomics.. Type operator-- (int); @@ -202,7 +213,11 @@ inline int32 Atomic::get() const noexcept #ifdef CARLA_PROPER_CPP11_SUPPORT static_wassert (sizeof (int32) == 4); #endif +#ifdef _MSC_VER + return castFromLong (_InterlockedExchangeAdd (reinterpret_cast (&value), 0)); +#else return castFrom32Bit ((int32) __sync_add_and_fetch (const_cast(&value), 0)); +#endif } template<> @@ -211,7 +226,11 @@ inline int64 Atomic::get() const noexcept #ifdef CARLA_PROPER_CPP11_SUPPORT static_wassert (sizeof (int64) == 8); #endif +#ifdef _MSC_VER + return castFrom64Bit (_InterlockedExchangeAdd64 (reinterpret_cast (&value), 0)); +#else return castFrom64Bit ((int64) __sync_add_and_fetch (const_cast(&value), 0)); +#endif } template<> @@ -220,7 +239,11 @@ inline uint32 Atomic::get() const noexcept #ifdef CARLA_PROPER_CPP11_SUPPORT static_wassert (sizeof (uint32) == 4); #endif +#ifdef _MSC_VER + return castFromLong (_InterlockedExchangeAdd (reinterpret_cast (&value), 0)); +#else return castFrom32Bit ((uint32) __sync_add_and_fetch (const_cast(&value), 0)); +#endif } template<> @@ -229,21 +252,35 @@ inline uint64 Atomic::get() const noexcept #ifdef CARLA_PROPER_CPP11_SUPPORT static_wassert (sizeof (uint64) == 8); #endif +#ifdef _MSC_VER + return castFrom64Bit (_InterlockedExchangeAdd64 (reinterpret_cast (&value), 0)); +#else return castFrom64Bit ((uint64) __sync_add_and_fetch (const_cast(&value), 0)); +#endif } template inline Type Atomic::exchange (const Type newValue) noexcept { +#ifdef _MSC_VER + return sizeof (Type) == 4 ? castFromLong (_InterlockedExchange (reinterpret_cast (&value), castToLong (newValue))) + : castFrom64Bit (_InterlockedExchange64 (reinterpret_cast (&value), castTo64Bit (newValue))); +#else Type currentVal = value; while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; } return currentVal; +#endif } template inline Type Atomic::operator+= (const Type amountToAdd) noexcept { +#ifdef _MSC_VER + return sizeof (Type) == 4 ? castFromLong (_InterlockedExchangeAdd (reinterpret_cast (&value), castToLong (amountToAdd))) + : castFrom64Bit (_InterlockedExchangeAdd64 (reinterpret_cast (&value), castTo64Bit (amountToAdd))); +#else return (Type) __sync_add_and_fetch (&value, amountToAdd); +#endif } template @@ -255,35 +292,58 @@ inline Type Atomic::operator-= (const Type amountToSubtract) noexcept template inline Type Atomic::operator++() noexcept { +#ifdef _MSC_VER + return sizeof (Type) == 4 ? castFromLong (_InterlockedIncrement (reinterpret_cast (&value))) + : castFrom64Bit (_InterlockedIncrement64 (reinterpret_cast (&value))); +#else return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) 1) : (Type) __sync_add_and_fetch ((volatile int64*) &value, 1); +#endif } template inline Type Atomic::operator--() noexcept { +#ifdef _MSC_VER + return sizeof (Type) == 4 ? castFromLong (_InterlockedDecrement (reinterpret_cast (&value))) + : castFrom64Bit (_InterlockedDecrement64 (reinterpret_cast (&value))); +#else return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) -1) : (Type) __sync_add_and_fetch ((volatile int64*) &value, -1); +#endif } template inline bool Atomic::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept { +#ifdef _MSC_VER + return compareAndSetValue (newValue, valueToCompare) == valueToCompare; +#else return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)) : __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)); +#endif } template inline Type Atomic::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept { - return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))) - : castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue))); +#ifdef _MSC_VER + return sizeof (Type) == 4 ? castFromLong (_InterlockedCompareExchange (reinterpret_cast (&value), castToLong (valueToCompare), castToLong (newValue))) + : castFrom64Bit (_InterlockedCompareExchange64 (reinterpret_cast (&value), castTo64Bit (valueToCompare), castTo64Bit (newValue))); +#else + return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap (reinterpret_cast (&value), castTo32Bit (valueToCompare), castTo32Bit (newValue))) + : castFrom64Bit ((int64) __sync_val_compare_and_swap (reinterpret_cast (&value), castTo64Bit (valueToCompare), castTo64Bit (newValue))); +#endif } template inline void Atomic::memoryBarrier() noexcept { +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else __sync_synchronize(); +#endif } #if defined(__clang__) diff --git a/source/modules/water/water.obs.cpp b/source/modules/water/water.obs.cpp index c9e26ea44..853953316 100644 --- a/source/modules/water/water.obs.cpp +++ b/source/modules/water/water.obs.cpp @@ -64,7 +64,7 @@ HINSTANCE getCurrentModuleInstanceHandle() noexcept #include "streams/OutputStream.cpp" // #include "synthesisers/Synthesiser.cpp" -// + #include "text/CharacterFunctions.cpp" #include "text/Identifier.cpp" #include "text/StringArray.cpp"