From 978b5028719b86964844e6a7a4a491a8a2499b12 Mon Sep 17 00:00:00 2001 From: Brendan Moran Date: Wed, 11 Nov 2015 15:19:37 +0000 Subject: [PATCH 1/3] Prototype Function Pointer Reduces instance count of passed arguments Requires C++11 Allows lambdas Uses virtual inheritance instead of member caller --- core-util/v2/FunctionPointer.hpp | 101 +++++++++++++++ core-util/v2/impl/FP0.hpp | 214 +++++++++++++++++++++++++++++++ core-util/v2/impl/FP1.hpp | 209 ++++++++++++++++++++++++++++++ 3 files changed, 524 insertions(+) create mode 100644 core-util/v2/FunctionPointer.hpp create mode 100644 core-util/v2/impl/FP0.hpp create mode 100644 core-util/v2/impl/FP1.hpp diff --git a/core-util/v2/FunctionPointer.hpp b/core-util/v2/FunctionPointer.hpp new file mode 100644 index 0000000..63edb89 --- /dev/null +++ b/core-util/v2/FunctionPointer.hpp @@ -0,0 +1,101 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * 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. + */ +#ifndef __FUNCTIONPOINTER_HPP__ +#define __FUNCTIONPOINTER_HPP__ + +#include +#include +#include +#include +#include +#include +#include + +namespace mbed { +namespace util { + +template +class FunctionPointerInterface; + +class FunctionPointerStorage { +public: + // Forward declaration of an unknown class + class UnknownClass; + // Forward declaration of an unknown member function to this an unknown class + // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard). + // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size + // and biggest alignment possible for member function. + // This type can be used inside unions, it will help to provide the storage + // with the proper size and alignment guarantees + typedef void (UnknownClass::*UnknownFunctionMember_t)(); + + union { + void * _static_fp; + struct { + union { + char _member[sizeof(UnknownFunctionMember_t)]; + UnknownFunctionMember_t _alignementAndSizeGuarantees; + }; + void * _object; + } _method; + char _functor_storage[sizeof(UnknownFunctionMember_t) + sizeof(void *)]; + void * _external_functor; + }; +}; + +template +class FunctionPointerImpl : public FunctionPointerInterface { +public: + FunctionPointerStorage _fp; +}; + +template +class FPAlignmentAndSize; + +template +T&& forward(typename std::remove_reference::type& a) noexcept +{ + return static_cast(a); +} +template +T&& forward(typename std::remove_reference::type&& a) noexcept +{ + return static_cast(a); +} + +template +class FunctionPointer; + +template +class FunctionPointerBind; + +template +class StaticPointer; + +template +class MethodPointer; + +template +class FunctorPointer; + + + +#include "impl/FP0.hpp" +#include "impl/FP1.hpp" +} // namespace util +} // namespace mbed + +#endif diff --git a/core-util/v2/impl/FP0.hpp b/core-util/v2/impl/FP0.hpp new file mode 100644 index 0000000..5819bee --- /dev/null +++ b/core-util/v2/impl/FP0.hpp @@ -0,0 +1,214 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * 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. + */ +#ifndef __FUNCTIONPOINTER_IMPL_FP0_HPP__ +#define __FUNCTIONPOINTER_IMPL_FP0_HPP__ +#ifndef __FUNCTIONPOINTER_HPP__ +#error FP0.hpp is an internal file that should only be called from inside FunctionPointer.hpp +#endif + +template +class FunctionPointerInterface{ +public: + virtual operator bool() const = 0; + virtual bool operator ==(const FunctionPointerInterface &) const = 0; + virtual FunctionPointerInterface & operator =(const FunctionPointerInterface &) = 0; + virtual R call(void) const = 0; + virtual ~FunctionPointerInterface(){}; + virtual void copy_to(void *) const = 0; +}; +template +class FPAlignmentAndSize : public FunctionPointerImpl { + operator bool() const {return false;} + bool operator ==(const FunctionPointerInterface & rhs) const { return false;} + FunctionPointerInterface & operator =(const FunctionPointerInterface &) { return *this; } + R call (void) const { return R();} + ~FPAlignmentAndSize() {} + void copy_to(void *target) const { + new(target) FPAlignmentAndSize(*this); + } +}; + +template +class FunctionPointer : FunctionPointerInterface { +public: + typedef struct arg_struct{ + } ArgStruct; + typedef R(*static_fp)(void); + + FunctionPointer(R (*fp)()) { + new(_storage) StaticPointer(fp); + } + template + FunctionPointer(C *c, R (C::*member)()) { + new(_storage) MethodPointer(c, member); + } + template + FunctionPointer(const F & f) { + new(_storage) FunctorPointer(f); + } + operator bool() const { + return *reinterpret_cast *>(&_storage); + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return *reinterpret_cast *>(&_storage) == rhs; + } + FunctionPointerInterface & operator=(const FunctionPointerInterface & rhs) { + reinterpret_cast*>(_storage)->~FunctionPointerImpl(); + rhs.copy_to(_storage); + return *this; + } + void copy_to(void *storage) const { + reinterpret_cast*>(_storage)->copy_to(storage); + } + inline R operator ()() const { + return call(); + } + R call() const { + return reinterpret_cast*>(_storage)->call(); + } + ~FunctionPointer() { + reinterpret_cast*>(_storage)->~FunctionPointerImpl(); + } +protected: + union { + char _storage[sizeof(FPAlignmentAndSize)]; + FPAlignmentAndSize _alignementAndSizeGuarantees; + }; +}; + +/** A class for storing and calling a pointer to a static or member void function without arguments + */ +template +class StaticPointer : public FunctionPointerImpl{ +public: + StaticPointer(R (*function)() = 0) + { + attach(function); + } + StaticPointer(const StaticPointer& fp) { + *this = fp; + } + void attach(R (*function)()) { + this->_fp._static_fp = (void*)function; + } + R call() const{ + return reinterpret_cast(this->_fp._static_fp)(); + } + R (*get_function() const)() { + return this->_fp._static_fp; + } + operator bool() const { + return (this->_fp._static_fp != NULL); + } + bool operator==(const FunctionPointerInterface & rhs) const { + return (this->_fp._static_fp == static_cast(&rhs)->_fp._static_fp); + } + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { + return *this = static_cast(rhs); + } + StaticPointer & operator = (const StaticPointer & rhs) { + this->_fp._static_fp = rhs._fp._static_fp; + return *this; + } + void copy_to(void * storage) const { + new(storage) StaticPointer(*this); + } +}; + +template +class MethodPointer : public FunctionPointerImpl{ +public: + MethodPointer(C *object, R (C::*member)(void)) + { + attach(object, member); + } + MethodPointer(const MethodPointer& fp) { + *this = fp; + } + void attach(C *object, R (C::*member)(void)) { + this->_fp._method._object = (void *) object; + *reinterpret_cast(this->_fp._method._member) = member; + } + R call() const{ + C* o = static_cast(this->_fp._method._object); + R (C::**m)(void) = reinterpret_cast(const_cast(this->_fp._method._member)); + return (o->**m)(); + } + R (*get_function() const)(){ + return NULL; + } + operator bool() const { + return (this->_fp._method._object != NULL); + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return (this->_fp._method._object == static_cast(&rhs)->_fp._method._object) && + (0 == memcmp(this->_fp._method._member, static_cast(&rhs)->_fp._method._member, sizeof(this->_fp._method._member))); + } + MethodPointer & operator = (const MethodPointer & rhs) { + this->_fp._method._object = rhs._fp._method._object; + memcpy(this->_fp._method._member, rhs._fp._method._member, sizeof(this->_fp._method._member)); + return *this; + } + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { + return *this = *static_cast(&rhs); + } + void copy_to(void * storage) const { + new(storage) MethodPointer(*this); + } +}; + +template +class FunctorPointer : public FunctionPointerImpl{ +public: + FunctorPointer(const F & f) + { + attach(f); + } + FunctorPointer(const FunctorPointer & fp) { + *this = fp; + } + void attach(const F & f) { + new(this->_fp._functor_storage)F(f); + } + R call() const{ + return reinterpret_cast(this->_fp._functor_storage)(); + } + R (*get_function() const)(){ + return NULL; + } + operator bool() const { + return (bool)reinterpret_cast(this->_fp._functor_storage); + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return (reinterpret_cast(this->_fp._functor_storage) == + reinterpret_cast(static_cast(rhs)._fp._functor_storage)); + } + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { + return *this = *static_cast(&rhs); + } + FunctorPointer & operator = (const FunctorPointer & rhs) { + new(this->_fp._functor_storage) F(reinterpret_cast(rhs._fp._functor_storage)); + return *this; + } + + void copy_to(void * storage) const { + new(storage) FunctorPointer(*this); + } + ~FunctorPointer() { + reinterpret_cast(this->_fp._functor_storage)->~F(); + } +}; +#endif diff --git a/core-util/v2/impl/FP1.hpp b/core-util/v2/impl/FP1.hpp new file mode 100644 index 0000000..c732090 --- /dev/null +++ b/core-util/v2/impl/FP1.hpp @@ -0,0 +1,209 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * 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. + */ +#ifndef __FUNCTIONPOINTER_IMPL_FP1_HPP__ +#define __FUNCTIONPOINTER_IMPL_FP1_HPP__ +#ifndef __FUNCTIONPOINTER_HPP__ +#error FP1.hpp is an internal file that should only be called from inside FunctionPointer.hpp +#endif + +template +class FunctionPointerInterface : protected FunctionPointerStorage { +public: + virtual operator bool() const = 0; + virtual bool operator ==(const FunctionPointerInterface &) const = 0; + virtual FunctionPointerInterface & operator =(const FunctionPointerInterface &) = 0; + virtual R call(A1&&) const = 0; + virtual ~FunctionPointerInterface(){}; +protected: + virtual void copy_to(void *) const = 0; +}; + +template +class FPAlignmentAndSize : public FunctionPointerImpl { + operator bool() const {return false;} + bool operator ==(const FunctionPointerInterface & rhs) const { return false;} + FunctionPointerInterface & operator =(const FunctionPointerInterface &) { return *this; } + R call (A1&&) const { return R();} + ~FPAlignmentAndSize() {} +protected: + void copy_to(void *target) const { + new(target) FPAlignmentAndSize(*this); + } +}; + + +template +class FunctionPointer { +public: + typedef struct arg_struct{ + } ArgStruct; + typedef R(*static_fp)(A1); + FunctionPointer(R (*fp)(A1)) { + new(_storage) StaticPointer(fp); + } + template + FunctionPointer(C *c, R (C::*member)(A1)) { + new(_storage) MethodPointer(c, member); + } + template + FunctionPointer(const F & f) { + new(_storage) FunctorPointer(f); + } + operator bool() const { + return *reinterpret_cast *>(const_cast(_storage)); + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return *reinterpret_cast *>(const_cast(_storage)) == rhs; + } + inline R operator ()(A1&& a1) const { + return call(forward(a1)); + } + R call(A1&& a1) const { + return reinterpret_cast*>(_storage)->call(forward(a1)); + } + ~FunctionPointer() { + reinterpret_cast*>(_storage)->~FunctionPointerImpl(); + } +protected: + union { + char _storage[sizeof(FPAlignmentAndSize)]; + FPAlignmentAndSize _alignementAndSizeGuarantees; + }; +}; + +/** A class for storing and calling a pointer to a static or member void function without arguments + */ +template +class StaticPointer : public FunctionPointerImpl{ +public: + StaticPointer(R (*function)(A1) = 0) + { + attach(function); + } + StaticPointer(const StaticPointer& fp) { + *this = fp; + } + void attach(R (*function)(A1)) { + this->_fp._static_fp = (void*)function; + } + R call(A1&& a1) const{ + R (*f)(A1) = reinterpret_cast(this->_fp._static_fp); + return f(forward(a1)); + } + R (*get_function() const)(A1) { + return this->_fp._static_fp; + } + operator bool() const { + return (this->_fp._static_fp != NULL); + } + bool operator==(const FunctionPointerInterface & rhs) const { + return (this->_fp._static_fp == static_cast(&rhs)->_fp._static_fp); + } + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { + return *this = static_cast(rhs); + } + StaticPointer & operator = (const StaticPointer & rhs) { + this->_fp._static_fp = rhs._fp._static_fp; + return *this; + } + void copy_to(void * storage) const { + new(storage) StaticPointer(*this); + } +}; + +template +class MethodPointer : public FunctionPointerImpl{ +public: + MethodPointer(C *object, R (C::*member)(A1)) + { + attach(object, member); + } + MethodPointer(const MethodPointer& fp) { + MethodPointer::operator=(fp); + } + void attach(C *object, R (C::*member)(A1)) { + this->_fp._method._object = (void *) object; + *reinterpret_cast(this->_fp._method._member) = member; + } + R call(A1&& a1) const{ + C* o = static_cast(this->_fp._method._object); + R (C::**m)(A1) = reinterpret_cast(const_cast(this->_fp._method._member)); + return (o->**m)(forward(a1)); + } + R (*get_function() const)(){ + return NULL; + } + operator bool() const { + return (this->_fp._method._object != NULL); + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return (this->_fp._method._object == static_cast(&rhs)->_method._object) && + (0 == memcmp(this->_fp._method._member, static_cast(&rhs)->_method._member, sizeof(this->_fp._method._member))); + } + MethodPointer & operator = (const MethodPointer & rhs) { + this->_fp._method._object = rhs._fp._method._object; + memcpy(this->_fp._method._member, rhs._fp._method._member, sizeof(this->_fp._method._member)); + return *this; + } + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { + return *this = *static_cast(&rhs); + } + void copy_to(void * storage) const { + new(storage) MethodPointer(*this); + } +}; + +template +class FunctorPointer : public FunctionPointerImpl{ +public: + FunctorPointer(const F & f) + { + attach(f); + } + FunctorPointer(const FunctorPointer & fp) { + *this = fp; + } + void attach(const F & f) { + new(this->_fp._functor_storage)F(f); + } + R call(A1&& a1) const{ + return reinterpret_cast(this->_fp._functor_storage)(forward(a1)); + } + R (*get_function() const)(){ + return NULL; + } + operator bool() const { + return (bool)reinterpret_cast(this->_fp._functor_storage); + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return (reinterpret_cast(this->_fp._functor_storage) == + reinterpret_cast(static_cast(&rhs)->_fp._functor_storage)); + } + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { + return *this = *static_cast(&rhs); + } + FunctorPointer & operator = (const FunctorPointer & rhs) { + new(this->_fp._functor_storage) F(reinterpret_cast(rhs._fp._functor_storage)); + return *this; + } + void copy_to(void * storage) const { + new(storage) FunctorPointer(*this); + } + ~FunctorPointer() { + reinterpret_cast(this->_fp._functor_storage)->~F(); + } +}; +#endif From 974cd4e78842c0a268fdbb7fad3411a836614dad Mon Sep 17 00:00:00 2001 From: Brendan Moran Date: Thu, 12 Nov 2015 09:25:34 +0000 Subject: [PATCH 2/3] Improvements to support bind Remove templates from size guarantee object Move implementation details into an impl namespace Support large functors --- core-util/v2/FunctionPointer.hpp | 25 +++--- core-util/v2/impl/FP0.hpp | 139 ++++++++++++++++++------------- core-util/v2/impl/FP1.hpp | 122 +++++++++++++++++---------- 3 files changed, 170 insertions(+), 116 deletions(-) diff --git a/core-util/v2/FunctionPointer.hpp b/core-util/v2/FunctionPointer.hpp index 63edb89..d2797ee 100644 --- a/core-util/v2/FunctionPointer.hpp +++ b/core-util/v2/FunctionPointer.hpp @@ -23,10 +23,13 @@ #include #include #include +#include namespace mbed { namespace util { + +namespace impl{ template class FunctionPointerInterface; @@ -43,6 +46,7 @@ class FunctionPointerStorage { typedef void (UnknownClass::*UnknownFunctionMember_t)(); union { + void * _static_fp; struct { union { @@ -56,15 +60,15 @@ class FunctionPointerStorage { }; }; -template -class FunctionPointerImpl : public FunctionPointerInterface { +class FunctionPointerSize0 { public: FunctionPointerStorage _fp; + virtual void nullmethod()=0; +}; +class FunctionPointerSize : public FunctionPointerSize0 { +public: + void nullmethod() {} }; - -template -class FPAlignmentAndSize; - template T&& forward(typename std::remove_reference::type& a) noexcept { @@ -76,12 +80,6 @@ T&& forward(typename std::remove_reference::type&& a) noexcept return static_cast(a); } -template -class FunctionPointer; - -template -class FunctionPointerBind; - template class StaticPointer; @@ -90,7 +88,10 @@ class MethodPointer; template class FunctorPointer; +} +template +class FunctionPointer; #include "impl/FP0.hpp" diff --git a/core-util/v2/impl/FP0.hpp b/core-util/v2/impl/FP0.hpp index 5819bee..c42d33d 100644 --- a/core-util/v2/impl/FP0.hpp +++ b/core-util/v2/impl/FP0.hpp @@ -19,80 +19,69 @@ #error FP0.hpp is an internal file that should only be called from inside FunctionPointer.hpp #endif -template -class FunctionPointerInterface{ -public: - virtual operator bool() const = 0; - virtual bool operator ==(const FunctionPointerInterface &) const = 0; - virtual FunctionPointerInterface & operator =(const FunctionPointerInterface &) = 0; - virtual R call(void) const = 0; - virtual ~FunctionPointerInterface(){}; - virtual void copy_to(void *) const = 0; -}; -template -class FPAlignmentAndSize : public FunctionPointerImpl { - operator bool() const {return false;} - bool operator ==(const FunctionPointerInterface & rhs) const { return false;} - FunctionPointerInterface & operator =(const FunctionPointerInterface &) { return *this; } - R call (void) const { return R();} - ~FPAlignmentAndSize() {} - void copy_to(void *target) const { - new(target) FPAlignmentAndSize(*this); - } -}; - template -class FunctionPointer : FunctionPointerInterface { +class FunctionPointer { public: typedef struct arg_struct{ } ArgStruct; typedef R(*static_fp)(void); FunctionPointer(R (*fp)()) { - new(_storage) StaticPointer(fp); + new(_storage) impl::StaticPointer(fp); } template FunctionPointer(C *c, R (C::*member)()) { - new(_storage) MethodPointer(c, member); + new(_storage) impl::MethodPointer(c, member); } template FunctionPointer(const F & f) { - new(_storage) FunctorPointer(f); + new(_storage) impl::FunctorPointer(f); } operator bool() const { - return *reinterpret_cast *>(&_storage); + return *reinterpret_cast *>(&_storage); } - bool operator ==(const FunctionPointerInterface & rhs) const { - return *reinterpret_cast *>(&_storage) == rhs; + bool operator ==(const FunctionPointer & rhs) const { + return *reinterpret_cast *>(&_storage) == + *reinterpret_cast *>(rhs.storage); } - FunctionPointerInterface & operator=(const FunctionPointerInterface & rhs) { - reinterpret_cast*>(_storage)->~FunctionPointerImpl(); + FunctionPointer & operator=(const FunctionPointer & rhs) { + reinterpret_cast*>(_storage)->~FunctionPointerInterface(); rhs.copy_to(_storage); return *this; } - void copy_to(void *storage) const { - reinterpret_cast*>(_storage)->copy_to(storage); - } inline R operator ()() const { return call(); } R call() const { - return reinterpret_cast*>(_storage)->call(); + return reinterpret_cast*>(_storage)->call(); } ~FunctionPointer() { - reinterpret_cast*>(_storage)->~FunctionPointerImpl(); + reinterpret_cast*>(_storage)->~FunctionPointerInterface(); } protected: union { - char _storage[sizeof(FPAlignmentAndSize)]; - FPAlignmentAndSize _alignementAndSizeGuarantees; + char _storage[sizeof(impl::FunctionPointerSize)]; + impl::FunctionPointerSize _alignementAndSizeGuarantees; }; }; +namespace impl { +template +class FunctionPointerInterface{ +public: + virtual operator bool() const = 0; + virtual bool operator ==(const FunctionPointerInterface &) const = 0; + virtual R call(void) const = 0; + virtual ~FunctionPointerInterface(){}; + virtual void copy_to(void *) const = 0; +protected: + FunctionPointerStorage _fp; +}; + /** A class for storing and calling a pointer to a static or member void function without arguments */ template -class StaticPointer : public FunctionPointerImpl{ +class StaticPointer : public FunctionPointerInterface{ public: StaticPointer(R (*function)() = 0) { @@ -116,9 +105,6 @@ class StaticPointer : public FunctionPointerImpl{ bool operator==(const FunctionPointerInterface & rhs) const { return (this->_fp._static_fp == static_cast(&rhs)->_fp._static_fp); } - FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { - return *this = static_cast(rhs); - } StaticPointer & operator = (const StaticPointer & rhs) { this->_fp._static_fp = rhs._fp._static_fp; return *this; @@ -129,7 +115,7 @@ class StaticPointer : public FunctionPointerImpl{ }; template -class MethodPointer : public FunctionPointerImpl{ +class MethodPointer : public FunctionPointerInterface{ public: MethodPointer(C *object, R (C::*member)(void)) { @@ -162,16 +148,16 @@ class MethodPointer : public FunctionPointerImpl{ memcpy(this->_fp._method._member, rhs._fp._method._member, sizeof(this->_fp._method._member)); return *this; } - FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { - return *this = *static_cast(&rhs); - } void copy_to(void * storage) const { new(storage) MethodPointer(*this); } }; + + template -class FunctorPointer : public FunctionPointerImpl{ +class FunctorPointer : public FunctionPointerInterface{ + constexpr static const bool Internal = sizeof(F) <= sizeof(impl::FunctionPointerStorage); public: FunctorPointer(const F & f) { @@ -180,35 +166,72 @@ class FunctorPointer : public FunctionPointerImpl{ FunctorPointer(const FunctorPointer & fp) { *this = fp; } - void attach(const F & f) { + template + typename std::enable_if::value>::type + attach(const F & f) + { new(this->_fp._functor_storage)F(f); } + template + typename std::enable_if::value>::type + attach(const F & f) { + this->_fp._external_functor = new F(f); + } R call() const{ - return reinterpret_cast(this->_fp._functor_storage)(); + return const_ref()(); } R (*get_function() const)(){ return NULL; } operator bool() const { - return (bool)reinterpret_cast(this->_fp._functor_storage); + return true; } bool operator ==(const FunctionPointerInterface & rhs) const { - return (reinterpret_cast(this->_fp._functor_storage) == - reinterpret_cast(static_cast(rhs)._fp._functor_storage)); - } - FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { - return *this = *static_cast(&rhs); + return false; } FunctorPointer & operator = (const FunctorPointer & rhs) { - new(this->_fp._functor_storage) F(reinterpret_cast(rhs._fp._functor_storage)); + deallocate(); + attach(*reinterpret_cast(rhs._fp._functor_storage)); return *this; } - + ~FunctorPointer() { + deallocate(); + } void copy_to(void * storage) const { new(storage) FunctorPointer(*this); } - ~FunctorPointer() { +protected: + template + typename std::enable_if::value, const F &>::type + const_ref() const{ + return *reinterpret_cast(this->_fp._functor_storage); + } + template + typename std::enable_if::value, F &>::type + ref() { + return *reinterpret_cast(this->_fp._functor_storage); + } + template + typename std::enable_if::value>::type + deallocate() { reinterpret_cast(this->_fp._functor_storage)->~F(); } + + template + typename std::enable_if::value, const F &>::type + const_ref() const{ + return *reinterpret_cast(this->_fp._external_functor); + } + template + typename std::enable_if::value, F &>::type + ref() { + return *reinterpret_cast(this->_fp._external_functor); + } + template + typename std::enable_if::value>::type + deallocate() { + reinterpret_cast(this->_fp._external_functor)->~F(); + } }; +} #endif diff --git a/core-util/v2/impl/FP1.hpp b/core-util/v2/impl/FP1.hpp index c732090..900df58 100644 --- a/core-util/v2/impl/FP1.hpp +++ b/core-util/v2/impl/FP1.hpp @@ -19,32 +19,6 @@ #error FP1.hpp is an internal file that should only be called from inside FunctionPointer.hpp #endif -template -class FunctionPointerInterface : protected FunctionPointerStorage { -public: - virtual operator bool() const = 0; - virtual bool operator ==(const FunctionPointerInterface &) const = 0; - virtual FunctionPointerInterface & operator =(const FunctionPointerInterface &) = 0; - virtual R call(A1&&) const = 0; - virtual ~FunctionPointerInterface(){}; -protected: - virtual void copy_to(void *) const = 0; -}; - -template -class FPAlignmentAndSize : public FunctionPointerImpl { - operator bool() const {return false;} - bool operator ==(const FunctionPointerInterface & rhs) const { return false;} - FunctionPointerInterface & operator =(const FunctionPointerInterface &) { return *this; } - R call (A1&&) const { return R();} - ~FPAlignmentAndSize() {} -protected: - void copy_to(void *target) const { - new(target) FPAlignmentAndSize(*this); - } -}; - - template class FunctionPointer { public: @@ -52,42 +26,56 @@ class FunctionPointer { } ArgStruct; typedef R(*static_fp)(A1); FunctionPointer(R (*fp)(A1)) { - new(_storage) StaticPointer(fp); + new(_storage) impl::StaticPointer(fp); } template FunctionPointer(C *c, R (C::*member)(A1)) { - new(_storage) MethodPointer(c, member); + new(_storage) impl::MethodPointer(c, member); } template FunctionPointer(const F & f) { - new(_storage) FunctorPointer(f); + new(_storage) impl::FunctorPointer(f); } operator bool() const { - return *reinterpret_cast *>(const_cast(_storage)); + return *reinterpret_cast *>(const_cast(_storage)); } - bool operator ==(const FunctionPointerInterface & rhs) const { - return *reinterpret_cast *>(const_cast(_storage)) == rhs; + bool operator ==(const impl::FunctionPointerInterface & rhs) const { + return *reinterpret_cast *>(const_cast(_storage)) == rhs; } inline R operator ()(A1&& a1) const { - return call(forward(a1)); + return call(impl::forward(a1)); } R call(A1&& a1) const { - return reinterpret_cast*>(_storage)->call(forward(a1)); + return reinterpret_cast*>(_storage)->call(impl::forward(a1)); } ~FunctionPointer() { - reinterpret_cast*>(_storage)->~FunctionPointerImpl(); + reinterpret_cast*>(_storage)->~FunctionPointerInterface(); } protected: union { - char _storage[sizeof(FPAlignmentAndSize)]; - FPAlignmentAndSize _alignementAndSizeGuarantees; + char _storage[sizeof(impl::FunctionPointerSize)]; + impl::FunctionPointerSize _alignementAndSizeGuarantees; }; }; +namespace impl { +template +class FunctionPointerInterface : protected impl::FunctionPointerStorage { +public: + virtual operator bool() const = 0; + virtual bool operator ==(const FunctionPointerInterface &) const = 0; + virtual FunctionPointerInterface & operator =(const FunctionPointerInterface &) = 0; + virtual R call(A1&&) const = 0; + virtual ~FunctionPointerInterface(){}; + virtual void copy_to(void *) const = 0; +protected: + impl::FunctionPointerStorage _fp; +}; + /** A class for storing and calling a pointer to a static or member void function without arguments */ template -class StaticPointer : public FunctionPointerImpl{ +class StaticPointer : public FunctionPointerInterface{ public: StaticPointer(R (*function)(A1) = 0) { @@ -125,7 +113,7 @@ class StaticPointer : public FunctionPointerImpl{ }; template -class MethodPointer : public FunctionPointerImpl{ +class MethodPointer : public FunctionPointerInterface{ public: MethodPointer(C *object, R (C::*member)(A1)) { @@ -167,7 +155,8 @@ class MethodPointer : public FunctionPointerImpl{ }; template -class FunctorPointer : public FunctionPointerImpl{ +class FunctorPointer : public FunctionPointerInterface{ + constexpr static const bool Internal = sizeof(F) <= sizeof(impl::FunctionPointerStorage); public: FunctorPointer(const F & f) { @@ -176,34 +165,75 @@ class FunctorPointer : public FunctionPointerImpl{ FunctorPointer(const FunctorPointer & fp) { *this = fp; } - void attach(const F & f) { + template + typename std::enable_if::value>::type + attach(const F & f) + { new(this->_fp._functor_storage)F(f); } + template + typename std::enable_if::value>::type + attach(const F & f) { + this->_fp._external_functor = new F(f); + } R call(A1&& a1) const{ - return reinterpret_cast(this->_fp._functor_storage)(forward(a1)); + return const_ref()(forward(a1)); } R (*get_function() const)(){ return NULL; } operator bool() const { - return (bool)reinterpret_cast(this->_fp._functor_storage); + return true; } bool operator ==(const FunctionPointerInterface & rhs) const { - return (reinterpret_cast(this->_fp._functor_storage) == - reinterpret_cast(static_cast(&rhs)->_fp._functor_storage)); + return false; } FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { return *this = *static_cast(&rhs); } FunctorPointer & operator = (const FunctorPointer & rhs) { - new(this->_fp._functor_storage) F(reinterpret_cast(rhs._fp._functor_storage)); + deallocate(); + attach(rhs.const_ref()); return *this; } void copy_to(void * storage) const { new(storage) FunctorPointer(*this); } ~FunctorPointer() { + deallocate(); + } +protected: + template + typename std::enable_if::value, const F &>::type + const_ref() const{ + return *reinterpret_cast(this->_fp._functor_storage); + } + template + typename std::enable_if::value, F &>::type + ref() { + return *reinterpret_cast(this->_fp._functor_storage); + } + template + typename std::enable_if::value>::type + deallocate() { reinterpret_cast(this->_fp._functor_storage)->~F(); } + + template + typename std::enable_if::value, const F &>::type + const_ref() const{ + return *reinterpret_cast(this->_fp._external_functor); + } + template + typename std::enable_if::value, F &>::type + ref() { + return *reinterpret_cast(this->_fp._external_functor); + } + template + typename std::enable_if::value>::type + deallocate() { + reinterpret_cast(this->_fp._external_functor)->~F(); + } }; +} #endif From 1278d532b619e703433cb8e37f04f9ab134f30ae Mon Sep 17 00:00:00 2001 From: Brendan Moran Date: Tue, 17 Nov 2015 22:12:24 +0000 Subject: [PATCH 3/3] Updates to allow binding in Function Pointer Add padding size as a template parameter to Function Pointer Add some utility methods to FunctionPointer Add a FPFunctor class, which acts like FunctionPointerBind Remove erroneous inheritance from FunctionPointerStorage --- core-util/v2/FunctionPointer.hpp | 28 ++++--- core-util/v2/impl/FP0.hpp | 49 +++++++------ core-util/v2/impl/FP1.hpp | 121 ++++++++++++++++++++----------- 3 files changed, 120 insertions(+), 78 deletions(-) diff --git a/core-util/v2/FunctionPointer.hpp b/core-util/v2/FunctionPointer.hpp index d2797ee..3bedb5b 100644 --- a/core-util/v2/FunctionPointer.hpp +++ b/core-util/v2/FunctionPointer.hpp @@ -30,9 +30,8 @@ namespace util { namespace impl{ -template -class FunctionPointerInterface; +template class FunctionPointerStorage { public: // Forward declaration of an unknown class @@ -46,7 +45,6 @@ class FunctionPointerStorage { typedef void (UnknownClass::*UnknownFunctionMember_t)(); union { - void * _static_fp; struct { union { @@ -55,19 +53,24 @@ class FunctionPointerStorage { }; void * _object; } _method; - char _functor_storage[sizeof(UnknownFunctionMember_t) + sizeof(void *)]; + char _raw_storage[sizeof(void*) + sizeof(UnknownFunctionMember_t) + I]; void * _external_functor; }; }; +template class FunctionPointerSize0 { public: - FunctionPointerStorage _fp; + FunctionPointerStorage _fp; virtual void nullmethod()=0; }; -class FunctionPointerSize : public FunctionPointerSize0 { + +template +class FunctionPointerSize : public FunctionPointerSize0 { public: void nullmethod() {} + FunctionPointerSize(){} + FunctionPointerSize(const FunctionPointerSize &){} }; template T&& forward(typename std::remove_reference::type& a) noexcept @@ -79,18 +82,23 @@ T&& forward(typename std::remove_reference::type&& a) noexcept { return static_cast(a); } +template +class FunctionPointerInterface; -template +template class StaticPointer; -template +template class MethodPointer; -template +template class FunctorPointer; } -template +template +class FPFunctor; + +template class FunctionPointer; diff --git a/core-util/v2/impl/FP0.hpp b/core-util/v2/impl/FP0.hpp index c42d33d..46b29a7 100644 --- a/core-util/v2/impl/FP0.hpp +++ b/core-util/v2/impl/FP0.hpp @@ -19,23 +19,23 @@ #error FP0.hpp is an internal file that should only be called from inside FunctionPointer.hpp #endif -template -class FunctionPointer { +template +class FunctionPointer { public: typedef struct arg_struct{ } ArgStruct; typedef R(*static_fp)(void); FunctionPointer(R (*fp)()) { - new(_storage) impl::StaticPointer(fp); + new(_storage) impl::StaticPointer(fp); } template FunctionPointer(C *c, R (C::*member)()) { - new(_storage) impl::MethodPointer(c, member); + new(_storage) impl::MethodPointer(c, member); } template FunctionPointer(const F & f) { - new(_storage) impl::FunctorPointer(f); + new(_storage) impl::FunctorPointer(f); } operator bool() const { return *reinterpret_cast *>(&_storage); @@ -60,14 +60,14 @@ class FunctionPointer { } protected: union { - char _storage[sizeof(impl::FunctionPointerSize)]; - impl::FunctionPointerSize _alignementAndSizeGuarantees; + char _storage[sizeof(impl::FunctionPointerSize)]; + impl::FunctionPointerSize _alignementAndSizeGuarantees; }; }; namespace impl { -template -class FunctionPointerInterface{ +template +class FunctionPointerInterface{ public: virtual operator bool() const = 0; virtual bool operator ==(const FunctionPointerInterface &) const = 0; @@ -75,13 +75,13 @@ class FunctionPointerInterface{ virtual ~FunctionPointerInterface(){}; virtual void copy_to(void *) const = 0; protected: - FunctionPointerStorage _fp; + FunctionPointerStorage _fp; }; /** A class for storing and calling a pointer to a static or member void function without arguments */ -template -class StaticPointer : public FunctionPointerInterface{ +template +class StaticPointer : public FunctionPointerInterface{ public: StaticPointer(R (*function)() = 0) { @@ -114,8 +114,8 @@ class StaticPointer : public FunctionPointerInterface{ } }; -template -class MethodPointer : public FunctionPointerInterface{ +template +class MethodPointer : public FunctionPointerInterface{ public: MethodPointer(C *object, R (C::*member)(void)) { @@ -155,22 +155,23 @@ class MethodPointer : public FunctionPointerInterface{ -template -class FunctorPointer : public FunctionPointerInterface{ - constexpr static const bool Internal = sizeof(F) <= sizeof(impl::FunctionPointerStorage); +template +class FunctorPointer : public FunctionPointerInterface{ + constexpr static const bool Internal = sizeof(F) <= sizeof(impl::FunctionPointerStorage); public: FunctorPointer(const F & f) { attach(f); } - FunctorPointer(const FunctorPointer & fp) { + FunctorPointer(const FunctorPointer & fp) + { *this = fp; } template typename std::enable_if::value>::type attach(const F & f) { - new(this->_fp._functor_storage)F(f); + new(this->_fp._raw_storage)F(f); } template typename std::enable_if::value>::type @@ -186,12 +187,12 @@ class FunctorPointer : public FunctionPointerInterface{ operator bool() const { return true; } - bool operator ==(const FunctionPointerInterface & rhs) const { + bool operator ==(const FunctionPointerInterface & rhs) const { return false; } FunctorPointer & operator = (const FunctorPointer & rhs) { deallocate(); - attach(*reinterpret_cast(rhs._fp._functor_storage)); + attach(*reinterpret_cast(rhs._fp._raw_storage)); return *this; } ~FunctorPointer() { @@ -204,17 +205,17 @@ class FunctorPointer : public FunctionPointerInterface{ template typename std::enable_if::value, const F &>::type const_ref() const{ - return *reinterpret_cast(this->_fp._functor_storage); + return *reinterpret_cast(this->_fp._raw_storage); } template typename std::enable_if::value, F &>::type ref() { - return *reinterpret_cast(this->_fp._functor_storage); + return *reinterpret_cast(this->_fp._raw_storage); } template typename std::enable_if::value>::type deallocate() { - reinterpret_cast(this->_fp._functor_storage)->~F(); + reinterpret_cast(this->_fp._raw_storage)->~F(); } template diff --git a/core-util/v2/impl/FP1.hpp b/core-util/v2/impl/FP1.hpp index 900df58..a9e2889 100644 --- a/core-util/v2/impl/FP1.hpp +++ b/core-util/v2/impl/FP1.hpp @@ -19,59 +19,82 @@ #error FP1.hpp is an internal file that should only be called from inside FunctionPointer.hpp #endif -template -class FunctionPointer { +template +class FunctionPointer { public: - typedef struct arg_struct{ - } ArgStruct; + FunctionPointer(const FunctionPointer &fp) { + fp.const_ref().copy_to(_storage); + } typedef R(*static_fp)(A1); FunctionPointer(R (*fp)(A1)) { - new(_storage) impl::StaticPointer(fp); + new(_storage) impl::StaticPointer(fp); } template FunctionPointer(C *c, R (C::*member)(A1)) { - new(_storage) impl::MethodPointer(c, member); + new(_storage) impl::MethodPointer(c, member); } template FunctionPointer(const F & f) { - new(_storage) impl::FunctorPointer(f); + new(_storage) impl::FunctorPointer(f); } operator bool() const { - return *reinterpret_cast *>(const_cast(_storage)); + return const_ref(); } bool operator ==(const impl::FunctionPointerInterface & rhs) const { - return *reinterpret_cast *>(const_cast(_storage)) == rhs; + return const_ref() == rhs; } - inline R operator ()(A1&& a1) const { - return call(impl::forward(a1)); + inline R operator ()(const A1&& a1) const { + return call(impl::forward(a1)); } - R call(A1&& a1) const { - return reinterpret_cast*>(_storage)->call(impl::forward(a1)); + R call(const A1&& a1) const { + return const_ref().call(impl::forward(a1)); + } + FPFunctor bind(const A1 &a1) const { + return FPFunctor(*this, a1); } ~FunctionPointer() { - reinterpret_cast*>(_storage)->~FunctionPointerInterface(); + (&ref())->~FunctionPointerInterface(); } protected: union { - char _storage[sizeof(impl::FunctionPointerSize)]; - impl::FunctionPointerSize _alignementAndSizeGuarantees; + char _storage[sizeof(impl::FunctionPointerSize)]; + impl::FunctionPointerSize _alignementAndSizeGuarantees; }; + impl::FunctionPointerInterface & ref() { + return *reinterpret_cast*>(_storage); + } + const impl::FunctionPointerInterface & const_ref() const { + return *reinterpret_cast*>(_storage); + } +}; + +template +class FPFunctor { +public: + FPFunctor(const FunctionPointer & fp, const A1 & a1) : _fp(fp), _a1(a1) {} + FPFunctor(const FPFunctor &other) : _fp(other._fp),_a1(other._a1) {} + R operator ()() const { + return _fp.call(impl::forward(_a1)); + } +protected: + FunctionPointer _fp; + A1 _a1; }; namespace impl { -template -class FunctionPointerInterface : protected impl::FunctionPointerStorage { +template +class FunctionPointerInterface { public: virtual operator bool() const = 0; virtual bool operator ==(const FunctionPointerInterface &) const = 0; - virtual FunctionPointerInterface & operator =(const FunctionPointerInterface &) = 0; - virtual R call(A1&&) const = 0; + virtual R call(const A1&&) const = 0; virtual ~FunctionPointerInterface(){}; virtual void copy_to(void *) const = 0; protected: - impl::FunctionPointerStorage _fp; + impl::FunctionPointerStorage _fp; }; + /** A class for storing and calling a pointer to a static or member void function without arguments */ template @@ -87,9 +110,13 @@ class StaticPointer : public FunctionPointerInterface{ void attach(R (*function)(A1)) { this->_fp._static_fp = (void*)function; } - R call(A1&& a1) const{ + template + FunctionPointer bind (A1&& a1) const { + return FunctionPointer(StaticFunctor(get_function(),forward(a1))); + } + R call(const A1&& a1) const{ R (*f)(A1) = reinterpret_cast(this->_fp._static_fp); - return f(forward(a1)); + return f(A1(forward(a1))); } R (*get_function() const)(A1) { return this->_fp._static_fp; @@ -112,6 +139,7 @@ class StaticPointer : public FunctionPointerInterface{ } }; + template class MethodPointer : public FunctionPointerInterface{ public: @@ -126,10 +154,14 @@ class MethodPointer : public FunctionPointerInterface{ this->_fp._method._object = (void *) object; *reinterpret_cast(this->_fp._method._member) = member; } - R call(A1&& a1) const{ + template + FunctionPointer bind (A1&& a1) const { + return FunctionPointer(); + } + R call(const A1&& a1) const{ C* o = static_cast(this->_fp._method._object); R (C::**m)(A1) = reinterpret_cast(const_cast(this->_fp._method._member)); - return (o->**m)(forward(a1)); + return (o->**m)(A1(forward(a1))); } R (*get_function() const)(){ return NULL; @@ -138,8 +170,8 @@ class MethodPointer : public FunctionPointerInterface{ return (this->_fp._method._object != NULL); } bool operator ==(const FunctionPointerInterface & rhs) const { - return (this->_fp._method._object == static_cast(&rhs)->_method._object) && - (0 == memcmp(this->_fp._method._member, static_cast(&rhs)->_method._member, sizeof(this->_fp._method._member))); + return (this->_fp._method._object == static_cast(&rhs)->_fp._method._object) && + (0 == memcmp(this->_fp._method._member, static_cast(&rhs)->_fp._method._member, sizeof(this->_fp._method._member))); } MethodPointer & operator = (const MethodPointer & rhs) { this->_fp._method._object = rhs._fp._method._object; @@ -154,9 +186,9 @@ class MethodPointer : public FunctionPointerInterface{ } }; -template -class FunctorPointer : public FunctionPointerInterface{ - constexpr static const bool Internal = sizeof(F) <= sizeof(impl::FunctionPointerStorage); +template +class FunctorPointer : public FunctionPointerInterface{ + constexpr static const bool Internal = sizeof(F) <= sizeof(impl::FunctionPointerStorage); public: FunctorPointer(const F & f) { @@ -169,15 +201,15 @@ class FunctorPointer : public FunctionPointerInterface{ typename std::enable_if::value>::type attach(const F & f) { - new(this->_fp._functor_storage)F(f); + new(this->_fp._raw_storage)F(f); } template typename std::enable_if::value>::type attach(const F & f) { this->_fp._external_functor = new F(f); } - R call(A1&& a1) const{ - return const_ref()(forward(a1)); + R call(const A1&& a1) const{ + return const_ref()(A1(forward(a1))); } R (*get_function() const)(){ return NULL; @@ -185,10 +217,10 @@ class FunctorPointer : public FunctionPointerInterface{ operator bool() const { return true; } - bool operator ==(const FunctionPointerInterface & rhs) const { + bool operator ==(const FunctionPointerInterface & rhs) const { return false; } - FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) { + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) const { return *this = *static_cast(&rhs); } FunctorPointer & operator = (const FunctorPointer & rhs) { @@ -202,28 +234,29 @@ class FunctorPointer : public FunctionPointerInterface{ ~FunctorPointer() { deallocate(); } -protected: template typename std::enable_if::value, const F &>::type const_ref() const{ - return *reinterpret_cast(this->_fp._functor_storage); + return *reinterpret_cast(this->_fp._raw_storage); } + template + typename std::enable_if::value, const F &>::type + const_ref() const{ + return *reinterpret_cast(this->_fp._external_functor); + } + +protected: template typename std::enable_if::value, F &>::type ref() { - return *reinterpret_cast(this->_fp._functor_storage); + return *reinterpret_cast(this->_fp._raw_storage); } template typename std::enable_if::value>::type deallocate() { - reinterpret_cast(this->_fp._functor_storage)->~F(); + reinterpret_cast(this->_fp._raw_storage)->~F(); } - template - typename std::enable_if::value, const F &>::type - const_ref() const{ - return *reinterpret_cast(this->_fp._external_functor); - } template typename std::enable_if::value, F &>::type ref() {