1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Added an OS X 10.5 compatible std::function replacement

This commit is contained in:
tpoole 2017-05-03 15:36:25 +01:00
parent db346fea6d
commit f4046909ab
20 changed files with 472 additions and 47 deletions

View file

@ -664,8 +664,7 @@
<MODULE id="juce_gui_extra" showAllCode="1"/>
</MODULES>
<LIVE_SETTINGS>
<OSX headerPath="~/SDKs/llvm/include&#10;~/SDKs/llvm/tools/clang/include"
enableCxx11="1" systemHeaderPath="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1&#10;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.2/include"/>
<OSX headerPath="" enableCxx11="1" systemHeaderPath=""/>
<WINDOWS enableCxx11="1"/>
<LINUX/>
</LIVE_SETTINGS>

View file

@ -383,6 +383,10 @@ private:
if (exporter->canLaunchProject())
defs << " " << exporter->getExporterIdentifierMacro() << "=1";
// Use the JUCE implementation of std::function until the live build
// engine can compile the one from the standard library
defs << " _LIBCPP_FUNCTIONAL=1";
return defs;
}

View file

@ -168,7 +168,6 @@ void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& desc
(new InvokeOnMessageThread (this, description, initialSampleRate, initialBufferSize, callback))->post();
}
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
@ -190,7 +189,6 @@ void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& desc
createPluginInstanceAsync (description, initialSampleRate, initialBufferSize, new CallbackInvoker (f));
}
#endif
void AudioPluginFormat::createPluginInstanceOnMessageThread (const PluginDescription& description,
double initialSampleRate,

View file

@ -92,12 +92,10 @@ public:
int initialBufferSize,
InstantiationCompletionCallback* completionCallback);
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
void createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
std::function<void (AudioPluginInstance*, const String&)> completionCallback);
#endif
/** Should do a quick check to see if this file or directory might be a plugin of
this format.

View file

@ -40,7 +40,6 @@ namespace PluginFormatManagerHelpers
ScopedPointer<AudioPluginFormat::InstantiationCompletionCallback> callback;
};
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
struct ErrorLambdaOnMessageThread : public CallbackMessage
{
ErrorLambdaOnMessageThread (const String& inError,
@ -54,7 +53,6 @@ namespace PluginFormatManagerHelpers
String error;
std::function<void (AudioPluginInstance*, const String&)> lambda;
};
#endif
}
AudioPluginFormatManager::AudioPluginFormatManager() {}
@ -139,7 +137,6 @@ void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescriptio
(new PluginFormatManagerHelpers::ErrorCallbackOnMessageThread (error, callback))->post();
}
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
@ -152,7 +149,6 @@ void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescriptio
(new PluginFormatManagerHelpers::ErrorLambdaOnMessageThread (error, f))->post();
}
#endif
AudioPluginFormat* AudioPluginFormatManager::findFormatForDescription (const PluginDescription& description, String& errorMessage) const
{

View file

@ -114,12 +114,10 @@ public:
int initialBufferSize,
AudioPluginFormat::InstantiationCompletionCallback* callback);
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
void createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
std::function<void (AudioPluginInstance*, const String&)> completionCallback);
#endif
/** Checks that the file or component for this plugin actually still exists.

View file

@ -24,8 +24,6 @@
==============================================================================
*/
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
//==============================================================================
struct AudioProcessorValueTreeState::Parameter : public AudioProcessorParameterWithID,
private ValueTree::Listener
@ -556,5 +554,3 @@ AudioProcessorValueTreeState::ButtonAttachment::ButtonAttachment (AudioProcessor
}
AudioProcessorValueTreeState::ButtonAttachment::~ButtonAttachment() {}
#endif

View file

@ -26,8 +26,6 @@
#pragma once
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
/**
This class contains a ValueTree which is used to manage an AudioProcessor's entire state.
@ -227,5 +225,3 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorValueTreeState)
};
#endif

View file

@ -52,11 +52,7 @@ public:
int numArguments;
};
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
using NativeFunction = std::function<var (const NativeFunctionArgs&)>;
#else
typedef var (*NativeFunction) (const NativeFunctionArgs&);
#endif
//==============================================================================
/** Creates a void variant. */

View file

@ -140,6 +140,7 @@ namespace juce
#include "misc/juce_RuntimePermissions.cpp"
#include "misc/juce_Result.cpp"
#include "misc/juce_Uuid.cpp"
#include "misc/juce_StdFunctionCompat.cpp"
#include "network/juce_MACAddress.cpp"
#include "network/juce_NamedPipe.cpp"
#include "network/juce_Socket.cpp"

View file

@ -107,7 +107,6 @@ public:
checkInvariants();
}
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
/** Creates a NormalisableRange with a given range and an injective mapping function.
@param rangeStart The minimum value in the range.
@ -135,17 +134,14 @@ public:
{
checkInvariants();
}
#endif
/** Uses the properties of this mapping to convert a non-normalised value to
its 0->1 representation.
*/
ValueType convertTo0to1 (ValueType v) const noexcept
{
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
if (convertTo0To1Function != nullptr)
return convertTo0To1Function (start, end, v);
#endif
ValueType proportion = (v - start) / (end - start);
@ -168,10 +164,8 @@ public:
*/
ValueType convertFrom0to1 (ValueType proportion) const noexcept
{
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
if (convertFrom0To1Function != nullptr)
return convertFrom0To1Function (start, end, proportion);
#endif
if (! symmetricSkew)
{
@ -196,10 +190,8 @@ public:
*/
ValueType snapToLegalValue (ValueType v) const noexcept
{
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
if (snapToLegalValueFunction != nullptr)
return snapToLegalValueFunction (start, end, v);
#endif
if (interval > ValueType())
v = start + interval * std::floor ((v - start) / interval + static_cast<ValueType> (0.5));
@ -274,9 +266,7 @@ private:
jassert (skew > ValueType());
}
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
std::function<ValueType (ValueType, ValueType, ValueType)> convertFrom0To1Function = nullptr,
convertTo0To1Function = nullptr,
snapToLegalValueFunction = nullptr;
#endif
};

View file

@ -79,11 +79,7 @@ public:
//==============================================================================
/** Function type of runtime permission request callbacks. */
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
typedef std::function<void (bool)> Callback;
#else
typedef void (*Callback) (bool);
#endif
//==============================================================================
/** Call this method to request a runtime permission.

View file

@ -0,0 +1,228 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
Permission is granted to use this software under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license/
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.
-----------------------------------------------------------------------------
To release a closed-source product which uses other parts of JUCE not
licensed under the ISC terms, commercial licenses are available: visit
www.juce.com for more information.
==============================================================================
*/
#if JUCE_UNIT_TESTS
namespace FunctionTestsHelpers
{
void incrementArgument (int& x) { x++; };
double multiply (double x, double a) noexcept { return a * x; };
struct AddOne
{
int operator()(int i) const { return i + 1; }
};
}
class FunctionTests : public UnitTest
{
public:
FunctionTests() : UnitTest ("Function") {}
void runTest() override
{
struct BigData
{
int content[32];
};
BigData bigData;
bigData.content[0] = 8;
{
beginTest ("Functions");
std::function<void(int&)> f1 (FunctionTestsHelpers::incrementArgument);
auto x = 0;
f1 (x);
expectEquals (x, 1);
std::function<double(double, double)> f2 (FunctionTestsHelpers::multiply);
expectEquals (6.0, f2 (2.0, 3.0));
}
{
beginTest ("Function objects");
std::function<int(int)> f1 = FunctionTestsHelpers::AddOne();
expectEquals (f1 (5), 6);
}
{
beginTest ("Lambdas");
std::function<int()> fStack ([]() { return 3; });
expectEquals (fStack(), 3);
std::function<int()> fHeap ([=]() { return bigData.content[0]; });
expectEquals (fHeap(), 8);
}
{
beginTest ("Boolean");
std::function<void(int&)> f1;
if (f1)
expect (false);
std::function<int()> f2 ([]() { return 3; });
if (! f2)
expect (false);
}
std::function<int()> fEmpty;
std::function<int()> fStack ([]() { return 3; });
std::function<int()> fHeap ([=]() { return bigData.content[0]; });
{
beginTest ("copy constructor");
std::function<int()> f1 (fStack);
expectEquals (f1(), 3);
std::function<int()> f2 (fHeap);
expectEquals (f2(), 8);
std::function<int()> f3 (fEmpty);
if (f3)
expect (false);
}
{
beginTest ("assignment");
std::function<int()> f1;
f1 = fStack;
expectEquals (f1(), 3);
std::function<int()> f2;
f2 = fHeap;
expectEquals (f2(), 8);
f1 = fHeap;
expectEquals (f1(), 8);
f2 = fStack;
expectEquals (f2(), 3);
f1 = fEmpty;
if (f1)
expect (false);
}
{
beginTest ("move constructor");
ScopedPointer<std::function<int()>> fStackTmp = new std::function<int()> (fStack);
std::function<int()> f1 (static_cast<std::function<int()>&&> (*fStackTmp));
fStackTmp = nullptr;
expectEquals (f1(), 3);
ScopedPointer<std::function<int()>> fHeapTmp = new std::function<int()> (fHeap);
std::function<int()> f2 (static_cast<std::function<int()>&&> (*fHeapTmp));
if (*fHeapTmp)
expect (false);
fHeapTmp = nullptr;
expectEquals (f2(), 8);
ScopedPointer<std::function<int()>> fEmptyTmp = new std::function<int()>();
std::function<int()> f3 (static_cast<std::function<int()>&&> (*fEmptyTmp));
fEmptyTmp = nullptr;
if (f3)
expect (false);
}
{
beginTest ("move assignment");
std::function<int()> f1 (fHeap);
ScopedPointer<std::function<int()>> fStackTmp = new std::function<int()> (fStack);
f1 = static_cast<std::function<int()>&&> (*fStackTmp);
fStackTmp = nullptr;
expectEquals (f1(), 3);
std::function<int()> f2 (fStack);
ScopedPointer<std::function<int()>> fHeapTmp = new std::function<int()> (fHeap);
f2 = static_cast<std::function<int()>&&> (*fHeapTmp);
if (*fHeapTmp)
expect (false);
fHeapTmp = nullptr;
expectEquals (f2(), 8);
std::function<int()> f3 (fHeap);
ScopedPointer<std::function<int()>> fEmptyTmp = new std::function<int()> ();
f3 = static_cast<std::function<int()>&&> (*fEmptyTmp);
fEmptyTmp = nullptr;
if (f3)
expect (false);
}
{
beginTest ("nullptr");
std::function<int()> f1 (nullptr);
if (f1)
expect (false);
std::function<int()> f2 ([]() { return 11; });
f2 = nullptr;
if (f2)
expect (false);
}
{
beginTest ("Swap");
std::function<int()> f1;
std::function<int()> f2 (fStack);
f2.swap (f1);
expectEquals (f1(), 3);
if (f2)
expect (false);
std::function<int()> f3 (fHeap);
f3.swap (f1);
expectEquals (f3(), 3);
expectEquals (f1(), 8);
}
}
};
static FunctionTests functionTests;
#endif

View file

@ -0,0 +1,225 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
Permission is granted to use this software under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license/
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.
-----------------------------------------------------------------------------
To release a closed-source product which uses other parts of JUCE not
licensed under the ISC terms, commercial licenses are available: visit
www.juce.com for more information.
==============================================================================
*/
#pragma once
namespace std
{
/**
This class provides an alternative to std::function that is compatible
with OS X 10.6 and earlier. This will only be used in OS X versions 10.6
and earlier and the Projucer live build.
*/
template <typename>
class function;
template <typename Result, typename... Arguments>
class function<Result (Arguments...)>
{
public:
/** Creates an empty function. */
function() noexcept {}
/** Creates an empty function. */
function (decltype (nullptr)) noexcept {}
/** Creates a function targetting the provided Functor. */
template <typename Functor>
function (Functor f)
{
functorHolderHelper = createFunctorStorage (sizeof (FunctorHolder<Functor, Result, Arguments...>));
new (functorHolderHelper) FunctorHolder<Functor, Result, Arguments...> (f);
}
/** Copy constructor. */
function (function const& other)
{
copy (other);
}
/** Move constructor */
function (function&& other)
{
move (other);
}
/** Destructor. */
~function()
{
release();
}
/** Replaces the contents of this function with the contents of another. */
function& operator= (function const& other)
{
release();
copy (other);
return *this;
}
/** Moves the contents of another function into this one. */
function& operator= (function&& other)
{
release();
move (other);
return *this;
}
/** Allows conditional expressions to test if this function is empty. */
explicit operator bool() const noexcept
{
return functorHolderHelper != nullptr;
}
/** Swaps the contents of this function with another. After this operation the
two functions will be pointing at each other's targets. */
void swap (function& other)
{
function<Result (Arguments...)> tmp (*this);
*this = other;
other = tmp;
}
/** Invokes the target of this function. */
Result operator() (Arguments... args) const
{
return (*functorHolderHelper) (args...);
}
bool operator== (decltype (nullptr)) const noexcept { return (functorHolderHelper == nullptr); }
bool operator!= (decltype (nullptr)) const noexcept { return (functorHolderHelper != nullptr); }
private:
//==============================================================================
template <typename ReturnType, typename... Args>
struct FunctorHolderBase
{
virtual ~FunctorHolderBase() {};
virtual size_t getSize() const noexcept = 0;
virtual FunctorHolderBase* copy (void*) const = 0;
virtual ReturnType operator()(Args...) = 0;
};
template <typename Functor, typename ReturnType, typename... Args>
struct FunctorHolder : FunctorHolderBase<Result, Arguments...>
{
FunctorHolder (Functor func) : f (func) {}
size_t getSize() const noexcept override final
{
return sizeof (*this);
}
FunctorHolder* copy (void* destination) const override final
{
return new (destination) FunctorHolder (f);
}
ReturnType operator()(Args... args) override final
{
return f (args...);
}
Functor f;
};
FunctorHolderBase<Result, Arguments...>* createFunctorStorage (size_t size)
{
void* storagePointer;
if (size > functorHolderStackSize)
{
if (heapFunctorStorage != nullptr)
{
delete [] heapFunctorStorage;
heapFunctorStorage = nullptr;
}
heapFunctorStorage = new char [size];
storagePointer = heapFunctorStorage;
}
else
{
storagePointer = &(stackFunctorStorage[0]);
}
return reinterpret_cast<FunctorHolderBase<Result, Arguments...>*> (storagePointer);
}
void copy (function const& other)
{
if (other.functorHolderHelper != nullptr)
{
functorHolderHelper = createFunctorStorage (other.functorHolderHelper->getSize());
other.functorHolderHelper->copy (functorHolderHelper);
}
}
void move (function& other)
{
functorHolderHelper = other.functorHolderHelper;
if (functorHolderHelper != nullptr)
{
if (functorHolderHelper->getSize() > functorHolderStackSize)
{
heapFunctorStorage = other.heapFunctorStorage;
other.heapFunctorStorage = nullptr;
}
else
{
std::copy (other.stackFunctorStorage, other.stackFunctorStorage + functorHolderStackSize,
stackFunctorStorage);
functorHolderHelper = reinterpret_cast<FunctorHolderBase<Result, Arguments...>*> (&(stackFunctorStorage[0]));
}
other.functorHolderHelper = nullptr;
}
}
void release()
{
if (functorHolderHelper != nullptr)
{
functorHolderHelper->~FunctorHolderBase<Result, Arguments...>();
functorHolderHelper = nullptr;
}
}
static const int functorHolderStackSize = 24;
char stackFunctorStorage[functorHolderStackSize];
char* heapFunctorStorage = nullptr;
FunctorHolderBase<Result, Arguments...>* functorHolderHelper = nullptr;
};
}

View file

@ -44,6 +44,7 @@
#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && ! defined (JUCE_COMPILER_SUPPORTS_LAMBDAS)
#define JUCE_COMPILER_SUPPORTS_LAMBDAS 1
#define JUCE_STDLIB_HAS_STD_FUNCTION_SUPPORT 1
#endif
#ifndef JUCE_EXCEPTIONS_DISABLED
@ -65,10 +66,14 @@
#define JUCE_DELETED_FUNCTION = delete
#endif
#if __has_feature (cxx_lambdas) && (defined (_LIBCPP_VERSION) || ! (JUCE_MAC || JUCE_IOS))
#if __has_feature (cxx_lambdas)
#define JUCE_COMPILER_SUPPORTS_LAMBDAS 1
#endif
#if (defined (_LIBCPP_VERSION) || ! (JUCE_MAC || JUCE_IOS))
#define JUCE_STDLIB_HAS_STD_FUNCTION_SUPPORT 1
#endif
#if __has_feature (cxx_generalized_initializers) && (defined (_LIBCPP_VERSION) || ! (JUCE_MAC || JUCE_IOS))
#define JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS 1
#endif
@ -106,6 +111,7 @@
#define JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS 1
#define JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES 1
#define JUCE_DELETED_FUNCTION = delete
#define JUCE_STDLIB_HAS_STD_FUNCTION_SUPPORT 1
#endif
#if _MSC_VER >= 1900

View file

@ -107,6 +107,12 @@
#undef minor
#undef KeyPress
// Include a replacement for std::function on older platforms and the live
// build
#if JUCE_PROJUCER_LIVE_BUILD || ! defined (JUCE_STDLIB_HAS_STD_FUNCTION_SUPPORT)
#include "../misc/juce_StdFunctionCompat.h"
#endif
//==============================================================================
// DLL building settings on Windows
#if JUCE_MSVC

View file

@ -341,7 +341,6 @@ void JUCE_CALLTYPE Timer::callPendingTimersSynchronously()
TimerThread::instance->callTimersSynchronously();
}
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
struct LambdaInvoker : private Timer
{
LambdaInvoker (int milliseconds, std::function<void()> f) : function (f)
@ -365,4 +364,3 @@ void JUCE_CALLTYPE Timer::callAfterDelay (int milliseconds, std::function<void()
{
new LambdaInvoker (milliseconds, f);
}
#endif

View file

@ -114,10 +114,8 @@ public:
int getTimerInterval() const noexcept { return timerPeriodMs; }
//==============================================================================
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
/** Invokes a lambda after a given number of milliseconds. */
static void JUCE_CALLTYPE callAfterDelay (int milliseconds, std::function<void()> functionToCall);
#endif
//==============================================================================
/** For internal use only: invokes any timers that need callbacks.

View file

@ -297,7 +297,6 @@ int ModalComponentManager::runEventLoopForCurrentComponent()
#endif
//==============================================================================
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
struct LambdaCallback : public ModalComponentManager::Callback
{
LambdaCallback (std::function<void(int)> fn) noexcept : function (fn) {}
@ -312,4 +311,3 @@ ModalComponentManager::Callback* ModalCallbackFunction::create (std::function<vo
{
return new LambdaCallback (f);
}
#endif

View file

@ -188,7 +188,6 @@ public:
return new FunctionCaller1<ParamType> (functionToCall, parameterValue);
}
#if JUCE_COMPILER_SUPPORTS_LAMBDAS
/** This is a utility function to create a ModalComponentManager::Callback that will
call a lambda function.
The lambda that you supply must take an integer parameter, which is the result code that
@ -197,7 +196,6 @@ public:
@see ModalComponentManager::Callback
*/
static ModalComponentManager::Callback* create (std::function<void(int)>);
#endif
//==============================================================================
/** This is a utility function to create a ModalComponentManager::Callback that will