/************************************************************************************ Filename : OVR_Delegates.h Content : C++ Delegates Created : June 15, 2014 Authors : Chris Taylor Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved. Licensed under the Oculus Master SDK License Version 1.0 (the "License"); you may not use the Oculus VR Rift SDK except in compliance with the License, which is provided at the time of installation or download, or which otherwise accompanies this software in either electronic or hard copy form. You may obtain a copy of the License at https://developer.oculus.com/licenses/oculusmastersdk-1.0 Unless required by applicable law or agreed to in writing, the Oculus VR SDK distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ************************************************************************************/ /* Based on The Impossibly Fast C++ Delegates by Sergey Ryazanov from http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx (2005) */ /* Usage: Declare a delegate with a void (int) signature, also known as a function that returns void and has one parameter that is an int: typedef Delegate1 MyDelegate; MyDelegate d; Point the delegate to a member function: d.SetMember(&a); d = MyDelegate::FromMember(&a); Point the delegate to a const member function: d.SetConstMember(&c); d = MyDelegate::FromConstMember(&c); Point the delegate to a free function: d.SetFree<&FreeFunctionX>(); d = MyDelegate::FromFree<&FreeFunctionX>(); Invoke the function via the delegate (works for all 3 cases): d(1000); By default the delegates are uninitialized. To clear an array of delegates quickly just zero the memory. This implementation is nicer than FastDelegates in my opinion because it is simple and easy to read. It is a little slower for virtual functions, but the size of the delegate is small, and it will only get better as compilers improve. */ #ifndef OVR_Delegates_h #define OVR_Delegates_h #include "OVR_Types.h" namespace OVR { template class Delegate0 { typedef ret_type (*StubPointer)(void*); typedef Delegate0 this_type; void* _object; StubPointer _stub; inline Delegate0(void* object, StubPointer stub) { _object = object; _stub = stub; } // Stubs template static inline ret_type FreeStub(void* /*object*/) { return (F)(); } template static inline ret_type MemberStub(void* object) { T* p = static_cast(object); return (p->*F)(); } template static inline ret_type ConstMemberStub(void* object) { T* p = static_cast(object); return (p->*F)(); } public: inline Delegate0() : _object(0), _stub(0) {} // Function invocation inline ret_type operator()() const { return (*_stub)(_object); } // Use stub pointer as a validity flag and equality checker inline bool operator==(const this_type& rhs) const { return _object == rhs._object && _stub == rhs._stub; } inline bool operator!=(const this_type& rhs) const { return _object != rhs._object || _stub != rhs._stub; } inline bool IsValid() const { return _stub != 0; } inline bool operator!() const { return _stub == 0; } inline void Invalidate() { _stub = 0; } // Delegate creation from a function template static inline this_type FromFree() { return this_type(0, &FreeStub); } template static inline this_type FromMember(T* object) { return this_type(object, &MemberStub); } template static inline this_type FromConstMember(T const* object) { return this_type(const_cast(object), &ConstMemberStub); } // In-place assignment to a different function template inline void SetFree() { *this = FromFree(); } template inline void SetMember(T* object) { *this = FromMember(object); } template inline void SetConstMember(T const* object) { *this = FromConstMember(object); } }; template class Delegate1 { typedef ret_type (*StubPointer)(void*, arg1_type); typedef Delegate1 this_type; void* _object; StubPointer _stub; inline Delegate1(void* object, StubPointer stub) { _object = object; _stub = stub; } // Stubs template static inline ret_type FreeStub(void* /*object*/, arg1_type a1) { return (F)(a1); } template static inline ret_type MemberStub(void* object, arg1_type a1) { T* p = static_cast(object); return (p->*F)(a1); } template static inline ret_type ConstMemberStub(void* object, arg1_type a1) { T* p = static_cast(object); return (p->*F)(a1); } public: inline Delegate1() : _object(0), _stub(0) {} // Function invocation inline ret_type operator()(arg1_type a1) const { return (*_stub)(_object, a1); } // Use stub pointer as a validity flag and equality checker inline bool operator==(const this_type& rhs) const { return _object == rhs._object && _stub == rhs._stub; } inline bool operator!=(const this_type& rhs) const { return _object != rhs._object || _stub != rhs._stub; } inline bool IsValid() const { return _stub != 0; } inline bool operator!() const { return _stub == 0; } inline void Invalidate() { _stub = 0; } // Delegate creation from a function template static inline this_type FromFree() { return this_type(0, &FreeStub); } template static inline this_type FromMember(T* object) { return this_type(object, &MemberStub); } template static inline this_type FromConstMember(T const* object) { return this_type(const_cast(object), &ConstMemberStub); } // In-place assignment to a different function template inline void SetFree() { *this = FromFree(); } template inline void SetMember(T* object) { *this = FromMember(object); } template inline void SetConstMember(T const* object) { *this = FromConstMember(object); } }; template class Delegate2 { typedef ret_type (*StubPointer)(void*, arg1_type, arg2_type); typedef Delegate2 this_type; void* _object; StubPointer _stub; inline Delegate2(void* object, StubPointer stub) { _object = object; _stub = stub; } // Stubs template static inline ret_type FreeStub(void* /*object*/, arg1_type a1, arg2_type a2) { return (F)(a1, a2); } template static inline ret_type MemberStub(void* object, arg1_type a1, arg2_type a2) { T* p = static_cast(object); return (p->*F)(a1, a2); } template static inline ret_type ConstMemberStub(void* object, arg1_type a1, arg2_type a2) { T* p = static_cast(object); return (p->*F)(a1, a2); } public: inline Delegate2() : _object(0), _stub(0) {} // Function invocation inline ret_type operator()(arg1_type a1, arg2_type a2) const { return (*_stub)(_object, a1, a2); } // Use stub pointer as a validity flag and equality checker inline bool operator==(const this_type& rhs) const { return _object == rhs._object && _stub == rhs._stub; } inline bool operator!=(const this_type& rhs) const { return _object != rhs._object || _stub != rhs._stub; } inline bool IsValid() const { return _stub != 0; } inline bool operator!() const { return _stub == 0; } inline void Invalidate() { _stub = 0; } // Delegate creation from a function template static inline this_type FromFree() { return this_type(0, &FreeStub); } template static inline this_type FromMember(T* object) { return this_type(object, &MemberStub); } template static inline this_type FromConstMember(T const* object) { return this_type(const_cast(object), &ConstMemberStub); } // In-place assignment to a different function template inline void SetFree() { *this = FromFree(); } template inline void SetMember(T* object) { *this = FromMember(object); } template inline void SetConstMember(T const* object) { *this = FromConstMember(object); } }; template class Delegate3 { typedef ret_type (*StubPointer)(void*, arg1_type, arg2_type, arg3_type); typedef Delegate3 this_type; void* _object; StubPointer _stub; inline Delegate3(void* object, StubPointer stub) { _object = object; _stub = stub; } // Stubs template static inline ret_type FreeStub(void* /*object*/, arg1_type a1, arg2_type a2, arg3_type a3) { return (F)(a1, a2, a3); } template static inline ret_type MemberStub(void* object, arg1_type a1, arg2_type a2, arg3_type a3) { T* p = static_cast(object); return (p->*F)(a1, a2, a3); } template static inline ret_type ConstMemberStub(void* object, arg1_type a1, arg2_type a2, arg3_type a3) { T* p = static_cast(object); return (p->*F)(a1, a2, a3); } public: inline Delegate3() : _object(0), _stub(0) {} // Function invocation inline ret_type operator()(arg1_type a1, arg2_type a2, arg3_type a3) const { return (*_stub)(_object, a1, a2, a3); } // Use stub pointer as a validity flag and equality checker inline bool operator==(const this_type& rhs) const { return _object == rhs._object && _stub == rhs._stub; } inline bool operator!=(const this_type& rhs) const { return _object != rhs._object || _stub != rhs._stub; } inline bool IsValid() const { return _stub != 0; } inline bool operator!() const { return _stub == 0; } inline void Invalidate() { _stub = 0; } // Delegate creation from a function template static inline this_type FromFree() { return this_type(0, &FreeStub); } template static inline this_type FromMember(T* object) { return this_type(object, &MemberStub); } template static inline this_type FromConstMember(T const* object) { return this_type(const_cast(object), &ConstMemberStub); } // In-place assignment to a different function template inline void SetFree() { *this = FromFree(); } template inline void SetMember(T* object) { *this = FromMember(object); } template inline void SetConstMember(T const* object) { *this = FromConstMember(object); } }; // Add more here if needed, but keep in mind that a short, simple interface // is rewarded by making the delegates faster... } // namespace OVR #endif // OVR_Delegates_h