207 lines
7.0 KiB
C++
207 lines
7.0 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
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.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
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.
|
|
|
|
@tags{Core}
|
|
*/
|
|
template <typename>
|
|
class function;
|
|
|
|
#ifndef DOXYGEN
|
|
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 targeting the provided Functor. */
|
|
template <typename Functor>
|
|
function (Functor f)
|
|
{
|
|
functorHolderHelper = getFunctorStorage (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 int getSize() const noexcept = 0;
|
|
virtual void 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) {}
|
|
|
|
int getSize() const noexcept override final
|
|
{
|
|
return sizeof (*this);
|
|
}
|
|
|
|
void copy (void* destination) const override final
|
|
{
|
|
new (destination) FunctorHolder (f);
|
|
}
|
|
|
|
ReturnType operator()(Args... args) override final
|
|
{
|
|
return f (args...);
|
|
}
|
|
|
|
Functor f;
|
|
};
|
|
|
|
FunctorHolderBase<Result, Arguments...>* getFunctorStorage (int size)
|
|
{
|
|
return reinterpret_cast<FunctorHolderBase<Result, Arguments...>*>
|
|
(size > functorHolderStackSize ? new char [static_cast<unsigned long> (size)]
|
|
: &(stackFunctorStorage[0]));
|
|
}
|
|
|
|
void copy (function const& other)
|
|
{
|
|
if (other.functorHolderHelper != nullptr)
|
|
{
|
|
functorHolderHelper = getFunctorStorage (other.functorHolderHelper->getSize());
|
|
other.functorHolderHelper->copy (functorHolderHelper);
|
|
}
|
|
}
|
|
|
|
void move (function& other)
|
|
{
|
|
if (other.functorHolderHelper != nullptr)
|
|
{
|
|
if (other.functorHolderHelper->getSize() > functorHolderStackSize)
|
|
{
|
|
functorHolderHelper = other.functorHolderHelper;
|
|
}
|
|
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];
|
|
|
|
FunctorHolderBase<Result, Arguments...>* functorHolderHelper = nullptr;
|
|
};
|
|
#endif
|
|
}
|