#ifndef WTF_Functional_h
#define WTF_Functional_h
#include "Assertions.h"
#include "PassRefPtr.h"
#include "RefPtr.h"
#include "ThreadSafeRefCounted.h"
namespace WTF {
template<typename T> class HasRefAndDeref {
typedef char YesType;
struct NoType {
char padding[8];
};
template<typename U, U, U> struct TypeChecker { };
template<typename U>
static YesType refAndDerefCheck(TypeChecker<void (U::*)(), &U::ref, &U::deref>*);
template<typename U>
static NoType refAndDerefCheck(...);
public:
static const bool value = sizeof(refAndDerefCheck<T>(0)) == sizeof(YesType);
};
template<typename> class FunctionWrapper;
template<typename R> class FunctionWrapper<R (*)()> {
public:
typedef R ResultType;
static const bool shouldRefFirstParameter = false;
explicit FunctionWrapper(R (*function)())
: m_function(function)
{
}
R operator()()
{
return m_function();
}
private:
R (*m_function)();
};
template<typename R, typename P0> class FunctionWrapper<R (*)(P0)> {
public:
typedef R ResultType;
static const bool shouldRefFirstParameter = false;
explicit FunctionWrapper(R (*function)(P0))
: m_function(function)
{
}
R operator()(P0 p0)
{
return m_function(p0);
}
private:
R (*m_function)(P0);
};
template<typename R, typename P0, typename P1> class FunctionWrapper<R (*)(P0, P1)> {
public:
typedef R ResultType;
static const bool shouldRefFirstParameter = false;
explicit FunctionWrapper(R (*function)(P0, P1))
: m_function(function)
{
}
R operator()(P0 p0, P1 p1)
{
return m_function(p0, p1);
}
private:
R (*m_function)(P0, P1);
};
template<typename R, typename C> class FunctionWrapper<R (C::*)()> {
public:
typedef R ResultType;
static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value;
explicit FunctionWrapper(R (C::*function)())
: m_function(function)
{
}
R operator()(C* c)
{
return (c->*m_function)();
}
private:
R (C::*m_function)();
};
template<typename R, typename C, typename P0> class FunctionWrapper<R (C::*)(P0)> {
public:
typedef R ResultType;
static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value;
explicit FunctionWrapper(R (C::*function)(P0))
: m_function(function)
{
}
R operator()(C* c, P0 p0)
{
return (c->*m_function)(p0);
}
private:
R (C::*m_function)(P0);
};
template<typename T, bool shouldRefAndDeref> struct RefAndDeref {
static void ref(T) { }
static void deref(T) { }
};
template<typename T> struct RefAndDeref<T*, true> {
static void ref(T* t) { t->ref(); }
static void deref(T* t) { t->deref(); }
};
class FunctionImplBase : public ThreadSafeRefCounted<FunctionImplBase> {
public:
virtual ~FunctionImplBase() { }
};
template<typename>
class FunctionImpl;
template<typename R>
class FunctionImpl<R ()> : public FunctionImplBase {
public:
virtual R operator()() = 0;
};
template<typename FunctionWrapper, typename FunctionType>
class BoundFunctionImpl;
template<typename FunctionWrapper, typename R> class BoundFunctionImpl<FunctionWrapper, R ()> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
public:
explicit BoundFunctionImpl(FunctionWrapper functionWrapper)
: m_functionWrapper(functionWrapper)
{
}
virtual R operator()()
{
return m_functionWrapper();
}
private:
FunctionWrapper m_functionWrapper;
};
template<typename FunctionWrapper, typename R, typename P0> class BoundFunctionImpl<FunctionWrapper, R (P0)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
public:
BoundFunctionImpl(FunctionWrapper functionWrapper, const P0& p0)
: m_functionWrapper(functionWrapper)
, m_p0(p0)
{
RefAndDeref<P0, FunctionWrapper::shouldRefFirstParameter>::ref(m_p0);
}
~BoundFunctionImpl()
{
RefAndDeref<P0, FunctionWrapper::shouldRefFirstParameter>::deref(m_p0);
}
virtual R operator()()
{
return m_functionWrapper(m_p0);
}
private:
FunctionWrapper m_functionWrapper;
P0 m_p0;
};
template<typename FunctionWrapper, typename R, typename P0, typename P1> class BoundFunctionImpl<FunctionWrapper, R (P0, P1)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
public:
BoundFunctionImpl(FunctionWrapper functionWrapper, const P0& p0, const P1& p1)
: m_functionWrapper(functionWrapper)
, m_p0(p0)
, m_p1(p1)
{
RefAndDeref<P0, FunctionWrapper::shouldRefFirstParameter>::ref(m_p0);
}
~BoundFunctionImpl()
{
RefAndDeref<P0, FunctionWrapper::shouldRefFirstParameter>::deref(m_p0);
}
virtual typename FunctionWrapper::ResultType operator()()
{
return m_functionWrapper(m_p0, m_p1);
}
private:
FunctionWrapper m_functionWrapper;
P0 m_p0;
P1 m_p1;
};
class FunctionBase {
public:
bool isNull() const
{
return !m_impl;
}
protected:
FunctionBase()
{
}
explicit FunctionBase(PassRefPtr<FunctionImplBase> impl)
: m_impl(impl)
{
}
template<typename FunctionType> FunctionImpl<FunctionType>* impl() const
{
return static_cast<FunctionImpl<FunctionType>*>(m_impl.get());
}
private:
RefPtr<FunctionImplBase> m_impl;
};
template<typename> class Function;
template<typename R>
class Function<R ()> : public FunctionBase {
public:
Function()
{
}
Function(PassRefPtr<FunctionImpl<R ()> > impl)
: FunctionBase(impl)
{
}
R operator()()
{
ASSERT(!isNull());
return impl<R ()>()->operator()();
}
};
template<typename FunctionType>
Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function)
{
return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType ()>(FunctionWrapper<FunctionType>(function))));
}
template<typename FunctionType, typename A1>
Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1)
{
return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1)>(FunctionWrapper<FunctionType>(function), a1)));
}
template<typename FunctionType, typename A1, typename A2>
Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2)
{
return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2)>(FunctionWrapper<FunctionType>(function), a1, a2)));
}
}
using WTF::Function;
using WTF::bind;
#endif // WTF_Functional_h