forked from jamboree/CxxFunctionBenchmark
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFastFunc.hpp
147 lines (124 loc) · 7.5 KB
/
FastFunc.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#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 AnyPtrThis = AnyClass*;
using AnyPtrFunc = void(AnyClass::*)();
template<typename TReturn = void, typename... TArgs> using AnyPtrFuncT = TReturn(AnyClass::*)(TArgs...);
template<typename TReturn = void, typename... TArgs> using AnyPtrStaticFuncT = TReturn(*)(TArgs...);
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 TN> struct SimplifyMemFunc
{
template<class TThis, class TFunc> inline static AnyPtrThis convert(const TThis*, TFunc, AnyPtrFunc&) noexcept
{
static_assert(TN - 100, "Unsupported member function pointer on this compiler");
return 0;
}
};
template<> struct SimplifyMemFunc<SingleMemFuncPtrSize>
{
template<class TThis, class TFunc> inline static AnyPtrThis convert(const TThis* mThis, TFunc mFunc, AnyPtrFunc& mFuncOut) noexcept
{
mFuncOut = reinterpret_cast<AnyPtrFunc>(mFunc);
return reinterpret_cast<AnyPtrThis>(const_cast<TThis*>(mThis));
}
};
template<typename TReturn, typename... TArgs> struct Closure
{
private:
using PtrFuncT = AnyPtrFuncT<TReturn, TArgs...>;
using PtrStaticFuncT = AnyPtrStaticFuncT<TReturn, TArgs...>;
AnyPtrThis ptrThis{nullptr};
AnyPtrFunc ptrFunction{nullptr};
public:
template<class TThis, class TFunc> inline void bind(TThis* mThis, TFunc mFunc) noexcept { ptrThis = SimplifyMemFunc<sizeof(mFunc)>::convert(mThis, mFunc, ptrFunction); }
template<class TThis, class TInvoker> inline void bind(TThis* mThis, TInvoker mInvoker, PtrStaticFuncT mFunc) noexcept
{
if(mFunc == nullptr) ptrFunction = nullptr; else bind(mThis, mInvoker);
ptrThis = horrible_cast<AnyPtrThis>(mFunc);
}
inline bool operator==(std::nullptr_t) const noexcept { return ptrThis == nullptr && ptrFunction == nullptr; }
inline bool operator==(const Closure& mRhs) const noexcept { return ptrThis == mRhs.ptrThis && ptrFunction == mRhs.ptrFunction; }
inline bool operator==(PtrStaticFuncT mPtr) const noexcept { return mPtr == nullptr ? *this == nullptr : mPtr == reinterpret_cast<PtrStaticFuncT>(getStaticFunc()); }
inline bool operator!=(std::nullptr_t) const noexcept { return !operator==(nullptr); }
inline bool operator!=(const Closure& mRhs) const noexcept { return !operator==(mRhs); }
inline bool operator!=(PtrStaticFuncT mPtr) const noexcept { return !operator==(mPtr); }
inline bool operator<(const Closure& mRhs) const { return ptrThis != mRhs.ptrThis ? ptrThis < mRhs.ptrThis : std::memcmp(&ptrFunction, &mRhs.ptrFunction, sizeof(ptrFunction)) < 0; }
inline bool operator>(const Closure& mRhs) const { return !operator<(mRhs); }
inline std::size_t getHash() const noexcept { return reinterpret_cast<std::size_t>(ptrThis) ^ Internal::unsafe_horrible_cast<std::size_t>(ptrFunction); }
inline AnyPtrThis getPtrThis() const noexcept { return ptrThis; }
inline PtrFuncT getPtrFunction() const noexcept { return reinterpret_cast<PtrFuncT>(ptrFunction); }
inline PtrStaticFuncT getStaticFunc() const noexcept { return horrible_cast<PtrStaticFuncT>(this); }
};
template<typename TReturn, typename... TArgs> class FastFuncImpl
{
private:
using PtrStaticFuncT = AnyPtrStaticFuncT<TReturn, TArgs...>;
Closure<TReturn, TArgs...> closure;
inline TReturn invokeStaticFunc(TArgs... mArgs) const { return (*(closure.getStaticFunc()))(std::forward<TArgs>(mArgs)...); }
protected:
template<class TThis, class TFunc> inline void bind(TThis* mThis, TFunc mFunc) noexcept { closure.bind(mThis, mFunc); }
template<class TFunc> inline void bind(TFunc mFunc) noexcept { closure.bind(this, &FastFuncImpl::invokeStaticFunc, mFunc); }
public:
inline FastFuncImpl() noexcept = default;
inline FastFuncImpl(std::nullptr_t) noexcept { }
inline FastFuncImpl(PtrStaticFuncT mFunc) noexcept { bind(mFunc); }
template<typename X, typename Y> inline FastFuncImpl(X* mThis, Y mFunc) noexcept { bind(mThis, mFunc); }
inline FastFuncImpl& operator=(PtrStaticFuncT mFunc) noexcept { bind(mFunc); }
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; }
inline bool operator==(PtrStaticFuncT 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); }
inline bool operator!=(PtrStaticFuncT 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 !operator<(mImpl); }
};
}
template<typename T> struct MemFuncToFunc;
template<typename TReturn, typename TThis, typename... TArgs> struct MemFuncToFunc<TReturn(TThis::*)(TArgs...) const> { using Type = TReturn(*)(TArgs...); };
#define ENABLE_IF_CONV_TO_FUN_PTR(x) typename std::enable_if<std::is_constructible<typename MemFuncToFunc<decltype(&std::decay<x>::type::operator())>::Type, x>::value>::type* = nullptr
#define ENABLE_IF_NOT_CONV_TO_FUN_PTR(x) typename std::enable_if<!std::is_constructible<typename MemFuncToFunc<decltype(&std::decay<x>::type::operator())>::Type, x>::value>::type* = nullptr
#define ENABLE_IF_SAME_TYPE(x, y) typename = typename std::enable_if<!std::is_same<x, typename std::decay<y>::type>{}>::type
template<typename T> 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, ENABLE_IF_SAME_TYPE(FastFunc, TFunc)> inline FastFunc(TFunc&& mFunc, ENABLE_IF_CONV_TO_FUN_PTR(TFunc))
{
using FuncType = typename std::decay<TFunc>::type;
this->bind(&mFunc, &FuncType::operator());
}
template<typename TFunc, ENABLE_IF_SAME_TYPE(FastFunc, TFunc)> inline FastFunc(TFunc&& mFunc, ENABLE_IF_NOT_CONV_TO_FUN_PTR(TFunc))
: 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->bind(storage.get(), &FuncType::operator());
}
};
#undef ENABLE_IF_CONV_TO_FUN_PTR
#undef ENABLE_IF_NOT_CONV_TO_FUN_PTR
#undef ENABLE_IF_SAME_TYPE
}
#endif