Created
September 6, 2013 16:21
-
-
Save vittorioromeo/6466177 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SSVU_FASTFUNC | |
#define SSVU_FASTFUNC | |
#include <cstring> | |
#include <type_traits> | |
#include <cassert> | |
#include <cstddef> | |
#include <memory> | |
#include <new> | |
#include <utility> | |
namespace ssvu | |
{ | |
namespace Internal | |
{ | |
class AnyClass; | |
using AnyMemFunc = void(Internal::AnyClass::*)(); | |
constexpr std::size_t SingleMemFuncPtrSize{sizeof(void(AnyClass::*)())}; | |
template<class TOut, class TIn> union HorribleUnion { TOut out; TIn in; }; | |
template<class TOut, class TIn> inline TOut horrible_cast(TIn mIn) noexcept { HorribleUnion<TOut, TIn> u; static_assert(sizeof(TIn) == sizeof(u) && sizeof(TIn) == sizeof(TOut), "Cannot use horrible_cast<>"); u.in = mIn; return u.out; } | |
template<class TOut, class TIn> inline TOut unsafe_horrible_cast(TIn mIn) noexcept { HorribleUnion<TOut, TIn> u; u.in = mIn; return u.out; } | |
template<std::size_t N> struct SimplifyMemFunc | |
{ | |
template<class X, class XFuncType, class AnyMemFunc> inline static AnyClass* convert(const X*, XFuncType, AnyMemFunc&) noexcept | |
{ | |
static_assert(N - 100, "Unsupported member function pointer on this compiler"); | |
return 0; | |
} | |
}; | |
template<> struct SimplifyMemFunc<SingleMemFuncPtrSize> | |
{ | |
template<class X, class XFuncType, class AnyMemFunc> inline static AnyClass* convert(const X* mPtrThis, XFuncType mFuncToBind, AnyMemFunc& mFuncBound) noexcept | |
{ | |
mFuncBound = reinterpret_cast<AnyMemFunc>(mFuncToBind); | |
return reinterpret_cast<AnyClass*>(const_cast<X*>(mPtrThis)); | |
} | |
}; | |
template<class TAnyMemFunc, class TStaticFunc> struct ClosurePtr | |
{ | |
private: | |
AnyClass* ptrThis{nullptr}; | |
AnyMemFunc ptrFunction{nullptr}; | |
public: | |
inline ClosurePtr() noexcept = default; | |
inline ClosurePtr(std::nullptr_t) noexcept { } | |
inline ClosurePtr(const ClosurePtr& mClosurePtr) noexcept : ptrThis{mClosurePtr.ptrThis}, ptrFunction{mClosurePtr.ptrFunction} { } | |
inline ClosurePtr(ClosurePtr&& mClosurePtr) noexcept : ptrThis{std::move(mClosurePtr.ptrThis)}, ptrFunction{std::move(mClosurePtr.ptrFunction)} { mClosurePtr = nullptr; } | |
inline ClosurePtr& operator=(std::nullptr_t) noexcept { ptrThis = nullptr; ptrFunction = nullptr; return *this; } | |
inline ClosurePtr& operator=(const ClosurePtr& mRhs) noexcept { ptrThis = mRhs.ptrThis; ptrFunction = mRhs.ptrFunction; return *this; } | |
inline ClosurePtr& operator=(ClosurePtr&& mRhs) noexcept { ptrThis = std::move(mRhs.ptrThis); ptrFunction = std::move(mRhs.ptrFunction); return *this; } | |
template<class X, class XMemFunc> inline void bindMemFunc(X* mPtrThis, XMemFunc mFuncToBind) noexcept { ptrThis = SimplifyMemFunc<sizeof(mFuncToBind)>::convert(mPtrThis, mFuncToBind, ptrFunction); } | |
template<class DerivedClass, class ParentInvokerSig, class SFunc> inline void bindStaticFunc(DerivedClass* mPtrParent, ParentInvokerSig mStaticFuncInvoker, SFunc mFuncToBind) noexcept | |
{ | |
static_assert(sizeof(AnyClass*) == sizeof(mFuncToBind), "Cannot use horrible_cast"); | |
if(mFuncToBind == nullptr) ptrFunction = nullptr; else bindMemFunc(mPtrParent, mStaticFuncInvoker); | |
ptrThis = horrible_cast<AnyClass*>(mFuncToBind); | |
} | |
inline bool operator==(std::nullptr_t) const noexcept { return ptrThis == nullptr && ptrFunction == nullptr; } | |
inline bool operator==(const ClosurePtr& mRhs) const noexcept { return ptrThis == mRhs.ptrThis && ptrFunction == mRhs.ptrFunction; } | |
inline bool operator==(TStaticFunc mPtr) const noexcept { return mPtr == nullptr ? *this == nullptr : mPtr == reinterpret_cast<TStaticFunc>(getStaticFunc()); } | |
inline bool operator!=(std::nullptr_t) const noexcept { return !operator==(nullptr); } | |
inline bool operator!=(const ClosurePtr& mRhs) const noexcept { return !operator==(mRhs); } | |
inline bool operator!=(TStaticFunc mPtr) const noexcept { return !operator==(mPtr); } | |
inline bool operator<(const ClosurePtr& mRhs) const { return ptrThis != mRhs.ptrThis ? ptrThis < mRhs.ptrThis : std::memcmp(&ptrFunction, &mRhs.ptrFunction, sizeof(ptrFunction)) < 0; } | |
inline bool operator>(const ClosurePtr& mRhs) const { return mRhs < *this; } | |
inline std::size_t getHash() const noexcept { return reinterpret_cast<std::size_t>(ptrThis) ^ Internal::unsafe_horrible_cast<std::size_t>(ptrFunction); } | |
inline AnyClass* getPtrThis() const noexcept { return ptrThis; } | |
inline TAnyMemFunc getPtrFunction() const noexcept { return reinterpret_cast<TAnyMemFunc>(ptrFunction); } | |
inline TStaticFunc getStaticFunc() const noexcept { static_assert(sizeof(TStaticFunc) == sizeof(this), "Cannot use horrible_cast"); return horrible_cast<TStaticFunc>(this); } | |
}; | |
template<typename TReturn, typename... TArgs> class FastFuncImpl | |
{ | |
protected: | |
using GenericMemFn = TReturn(Internal::AnyClass::*)(TArgs...); | |
template<typename TFRet> using FuncSig = TFRet(*)(TArgs...); | |
using ClosureType = Internal::ClosurePtr<GenericMemFn, TReturn(*)(TArgs...)>; | |
ClosureType closure; | |
private: | |
template<typename X> using XFuncToBind = TReturn(X::*)(TArgs...) const; | |
template<typename TFRet> inline TReturn invokeStaticFunc(TArgs... mArgs) const { return (*(closure.getStaticFunc()))(mArgs...); } | |
template<typename TFRet> inline void bind(FuncSig<TFRet> mFuncToBind) noexcept { closure.bindStaticFunc(this, &FastFuncImpl::invokeStaticFunc<TFRet>, mFuncToBind); } | |
template<typename X, typename Y> inline void bind(Y* mPtrThis, XFuncToBind<X> mFuncToBind) noexcept { closure.bindMemFunc(reinterpret_cast<const X*>(mPtrThis), mFuncToBind); } | |
public: | |
inline FastFuncImpl() noexcept = default; | |
inline FastFuncImpl(std::nullptr_t) noexcept { } | |
inline FastFuncImpl(const FastFuncImpl& mImpl) noexcept : closure{mImpl.closure} { } | |
inline FastFuncImpl(FastFuncImpl&& mImpl) noexcept : closure{std::move(mImpl.closure)} { } | |
template<typename TFRet> inline FastFuncImpl(FuncSig<TFRet> mFuncToBind) noexcept { bind(mFuncToBind); } | |
template<typename X, typename Y> inline FastFuncImpl(Y* mPtrThis, XFuncToBind<X> mFuncToBind) noexcept { bind(mPtrThis, mFuncToBind); } | |
inline void operator=(const FastFuncImpl& mImpl) noexcept { closure = mImpl.closure; } | |
inline void operator=(FastFuncImpl&& mImpl) noexcept { closure = std::move(mImpl.closure); } | |
template<typename TFRet> inline void operator=(FuncSig<TFRet> mFuncToBind) noexcept { bind(mFuncToBind); } | |
inline TReturn operator()(TArgs... mArgs) const { return (closure.getPtrThis()->*(closure.getPtrFunction()))(std::forward<TArgs>(mArgs)...); } | |
inline bool operator==(std::nullptr_t) const noexcept { return closure == nullptr; } | |
inline bool operator==(const FastFuncImpl& mImpl) const noexcept { return closure == mImpl.closure; } | |
template<typename TFRet> inline bool operator==(FuncSig<TFRet> mFuncPtr) const noexcept { return closure == mFuncPtr; } | |
inline bool operator!=(std::nullptr_t) const noexcept { return !operator==(nullptr); } | |
inline bool operator!=(const FastFuncImpl& mImpl) const noexcept { return !operator==(mImpl); } | |
template<typename TFRet> inline bool operator!=(FuncSig<TFRet> mFuncPtr) const noexcept { return !operator==(mFuncPtr); } | |
inline bool operator<(const FastFuncImpl& mImpl) const { return closure < mImpl.closure; } | |
inline bool operator>(const FastFuncImpl& mImpl) const { return closure > mImpl.closure; } | |
}; | |
} | |
template<typename TSignature> class FastFunc; | |
template<typename TReturn, typename... TArgs> class FastFunc<TReturn(TArgs...)> : public Internal::FastFuncImpl<TReturn, TArgs...> | |
{ | |
private: | |
using BaseType = Internal::FastFuncImpl<TReturn, TArgs...>; | |
std::shared_ptr<void> storage; | |
template<typename T> inline static void funcDeleter(void* mPtr) { static_cast<T*>(mPtr)->~T(); operator delete(mPtr); } | |
public: | |
using BaseType::BaseType; | |
inline FastFunc() noexcept = default; | |
template<typename TFunc, typename = typename std::enable_if<!std::is_same<FastFunc, typename std::decay<TFunc>::type>{}>::type> inline FastFunc(TFunc&& mFunc) | |
: storage(operator new(sizeof(TFunc)), funcDeleter<typename std::decay<TFunc>::type>) | |
{ | |
using FuncType = typename std::decay<TFunc>::type; | |
new (storage.get()) FuncType(std::forward<TFunc>(mFunc)); | |
this->closure.bindMemFunc(storage.get(), &FuncType::operator()); | |
} | |
}; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment