Make water atomic methods compatible with MSVC

Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
falkTX 2023-05-07 16:00:44 +02:00
parent f75582a2f3
commit e06df7ae82
No known key found for this signature in database
GPG Key ID: CDBAA37ABC74FBA0
3 changed files with 67 additions and 5 deletions

View File

@ -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 <falktx@falktx.com>
* Copyright (C) 2017-2023 Filipe Coelho <falktx@falktx.com>
*
* 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"

View File

@ -28,6 +28,15 @@
#include "../water.h"
#ifdef _MSC_VER
# ifndef NOMINMAX
# define NOMINMAX
# endif
# define WIN32_LEAN_AND_MEAN 1
# include <winsock2.h>
# include <windows.h>
#endif
#include <stdint.h>
namespace water {
@ -161,7 +170,7 @@ public:
#else
__attribute__ ((aligned (4)))
#endif
volatile Type value;
mutable volatile Type value;
private:
template <typename Dest, typename Source>
@ -171,8 +180,10 @@ private:
static inline Type castFrom64Bit (int64 value) noexcept { return castTo <Type, int64> (value); }
static inline Type castFrom32Bit (uint32 value) noexcept { return castTo <Type, uint32> (value); }
static inline Type castFrom64Bit (uint64 value) noexcept { return castTo <Type, uint64> (value); }
static inline Type castFromLong (long value) noexcept { return castTo <Type, long> (value); }
static inline int32 castTo32Bit (Type value) noexcept { return castTo <int32, Type> (value); }
static inline int64 castTo64Bit (Type value) noexcept { return castTo <int64, Type> (value); }
static inline long castToLong (Type value) noexcept { return castTo <long, Type> (value); }
Type operator++ (int); // better to just use pre-increment with atomics..
Type operator-- (int);
@ -202,7 +213,11 @@ inline int32 Atomic<int32>::get() const noexcept
#ifdef CARLA_PROPER_CPP11_SUPPORT
static_wassert (sizeof (int32) == 4);
#endif
#ifdef _MSC_VER
return castFromLong (_InterlockedExchangeAdd (reinterpret_cast<volatile long*> (&value), 0));
#else
return castFrom32Bit ((int32) __sync_add_and_fetch (const_cast<volatile int32*>(&value), 0));
#endif
}
template<>
@ -211,7 +226,11 @@ inline int64 Atomic<int64>::get() const noexcept
#ifdef CARLA_PROPER_CPP11_SUPPORT
static_wassert (sizeof (int64) == 8);
#endif
#ifdef _MSC_VER
return castFrom64Bit (_InterlockedExchangeAdd64 (reinterpret_cast<volatile int64*> (&value), 0));
#else
return castFrom64Bit ((int64) __sync_add_and_fetch (const_cast<volatile int64*>(&value), 0));
#endif
}
template<>
@ -220,7 +239,11 @@ inline uint32 Atomic<uint32>::get() const noexcept
#ifdef CARLA_PROPER_CPP11_SUPPORT
static_wassert (sizeof (uint32) == 4);
#endif
#ifdef _MSC_VER
return castFromLong (_InterlockedExchangeAdd (reinterpret_cast<volatile long*> (&value), 0));
#else
return castFrom32Bit ((uint32) __sync_add_and_fetch (const_cast<volatile uint32*>(&value), 0));
#endif
}
template<>
@ -229,21 +252,35 @@ inline uint64 Atomic<uint64>::get() const noexcept
#ifdef CARLA_PROPER_CPP11_SUPPORT
static_wassert (sizeof (uint64) == 8);
#endif
#ifdef _MSC_VER
return castFrom64Bit (_InterlockedExchangeAdd64 (reinterpret_cast<volatile int64*> (&value), 0));
#else
return castFrom64Bit ((uint64) __sync_add_and_fetch (const_cast<volatile uint64*>(&value), 0));
#endif
}
template <typename Type>
inline Type Atomic<Type>::exchange (const Type newValue) noexcept
{
#ifdef _MSC_VER
return sizeof (Type) == 4 ? castFromLong (_InterlockedExchange (reinterpret_cast<volatile long*> (&value), castToLong (newValue)))
: castFrom64Bit (_InterlockedExchange64 (reinterpret_cast<volatile int64*> (&value), castTo64Bit (newValue)));
#else
Type currentVal = value;
while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
return currentVal;
#endif
}
template <typename Type>
inline Type Atomic<Type>::operator+= (const Type amountToAdd) noexcept
{
#ifdef _MSC_VER
return sizeof (Type) == 4 ? castFromLong (_InterlockedExchangeAdd (reinterpret_cast<volatile long*> (&value), castToLong (amountToAdd)))
: castFrom64Bit (_InterlockedExchangeAdd64 (reinterpret_cast<volatile int64*> (&value), castTo64Bit (amountToAdd)));
#else
return (Type) __sync_add_and_fetch (&value, amountToAdd);
#endif
}
template <typename Type>
@ -255,35 +292,58 @@ inline Type Atomic<Type>::operator-= (const Type amountToSubtract) noexcept
template <typename Type>
inline Type Atomic<Type>::operator++() noexcept
{
#ifdef _MSC_VER
return sizeof (Type) == 4 ? castFromLong (_InterlockedIncrement (reinterpret_cast<volatile long*> (&value)))
: castFrom64Bit (_InterlockedIncrement64 (reinterpret_cast<volatile int64*> (&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 <typename Type>
inline Type Atomic<Type>::operator--() noexcept
{
#ifdef _MSC_VER
return sizeof (Type) == 4 ? castFromLong (_InterlockedDecrement (reinterpret_cast<volatile long*> (&value)))
: castFrom64Bit (_InterlockedDecrement64 (reinterpret_cast<volatile int64*> (&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 <typename Type>
inline bool Atomic<Type>::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 <typename Type>
inline Type Atomic<Type>::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<volatile long*> (&value), castToLong (valueToCompare), castToLong (newValue)))
: castFrom64Bit (_InterlockedCompareExchange64 (reinterpret_cast<volatile int64*> (&value), castTo64Bit (valueToCompare), castTo64Bit (newValue)));
#else
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap (reinterpret_cast<volatile int32*> (&value), castTo32Bit (valueToCompare), castTo32Bit (newValue)))
: castFrom64Bit ((int64) __sync_val_compare_and_swap (reinterpret_cast<volatile int64*> (&value), castTo64Bit (valueToCompare), castTo64Bit (newValue)));
#endif
}
template <typename Type>
inline void Atomic<Type>::memoryBarrier() noexcept
{
#ifdef _MSC_VER
_ReadWriteBarrier();
#else
__sync_synchronize();
#endif
}
#if defined(__clang__)

View File

@ -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"