diff --git a/core-util/v2/FunctionPointer.hpp b/core-util/v2/FunctionPointer.hpp new file mode 100644 index 0000000..3bedb5b --- /dev/null +++ b/core-util/v2/FunctionPointer.hpp @@ -0,0 +1,110 @@ +/* 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 +#include + +namespace mbed { +namespace util { + + +namespace impl{ + +template +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 _raw_storage[sizeof(void*) + sizeof(UnknownFunctionMember_t) + I]; + void * _external_functor; + }; +}; + +template +class FunctionPointerSize0 { +public: + FunctionPointerStorage _fp; + virtual void nullmethod()=0; +}; + +template +class FunctionPointerSize : public FunctionPointerSize0 { +public: + void nullmethod() {} + FunctionPointerSize(){} + FunctionPointerSize(const FunctionPointerSize &){} +}; +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 FunctionPointerInterface; + +template +class StaticPointer; + +template +class MethodPointer; + +template +class FunctorPointer; +} + +template +class FPFunctor; + +template +class FunctionPointer; + + +#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..46b29a7 --- /dev/null +++ b/core-util/v2/impl/FP0.hpp @@ -0,0 +1,238 @@ +/* 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 FunctionPointer { +public: + typedef struct arg_struct{ + } ArgStruct; + typedef R(*static_fp)(void); + + FunctionPointer(R (*fp)()) { + new(_storage) impl::StaticPointer(fp); + } + template + FunctionPointer(C *c, R (C::*member)()) { + new(_storage) impl::MethodPointer(c, member); + } + template + FunctionPointer(const F & f) { + new(_storage) impl::FunctorPointer(f); + } + operator bool() const { + return *reinterpret_cast *>(&_storage); + } + bool operator ==(const FunctionPointer & rhs) const { + return *reinterpret_cast *>(&_storage) == + *reinterpret_cast *>(rhs.storage); + } + FunctionPointer & operator=(const FunctionPointer & rhs) { + reinterpret_cast*>(_storage)->~FunctionPointerInterface(); + rhs.copy_to(_storage); + return *this; + } + inline R operator ()() const { + return call(); + } + R call() const { + return reinterpret_cast*>(_storage)->call(); + } + ~FunctionPointer() { + reinterpret_cast*>(_storage)->~FunctionPointerInterface(); + } +protected: + union { + 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 FunctionPointerInterface{ +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); + } + 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 FunctionPointerInterface{ +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; + } + void copy_to(void * storage) const { + new(storage) MethodPointer(*this); + } +}; + + + +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) + { + *this = fp; + } + template + typename std::enable_if::value>::type + attach(const 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() const{ + return const_ref()(); + } + R (*get_function() const)(){ + return NULL; + } + operator bool() const { + return true; + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return false; + } + FunctorPointer & operator = (const FunctorPointer & rhs) { + deallocate(); + attach(*reinterpret_cast(rhs._fp._raw_storage)); + return *this; + } + ~FunctorPointer() { + deallocate(); + } + void copy_to(void * storage) const { + new(storage) FunctorPointer(*this); + } +protected: + template + typename std::enable_if::value, const F &>::type + const_ref() const{ + return *reinterpret_cast(this->_fp._raw_storage); + } + template + typename std::enable_if::value, F &>::type + ref() { + return *reinterpret_cast(this->_fp._raw_storage); + } + template + typename std::enable_if::value>::type + deallocate() { + 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() { + 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 new file mode 100644 index 0000000..a9e2889 --- /dev/null +++ b/core-util/v2/impl/FP1.hpp @@ -0,0 +1,272 @@ +/* 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 FunctionPointer { +public: + FunctionPointer(const FunctionPointer &fp) { + fp.const_ref().copy_to(_storage); + } + typedef R(*static_fp)(A1); + FunctionPointer(R (*fp)(A1)) { + new(_storage) impl::StaticPointer(fp); + } + template + FunctionPointer(C *c, R (C::*member)(A1)) { + new(_storage) impl::MethodPointer(c, member); + } + template + FunctionPointer(const F & f) { + new(_storage) impl::FunctorPointer(f); + } + operator bool() const { + return const_ref(); + } + bool operator ==(const impl::FunctionPointerInterface & rhs) const { + return const_ref() == rhs; + } + inline R operator ()(const A1&& a1) const { + return 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() { + (&ref())->~FunctionPointerInterface(); + } +protected: + union { + 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 { +public: + virtual operator bool() const = 0; + virtual bool operator ==(const FunctionPointerInterface &) const = 0; + virtual R call(const 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 FunctionPointerInterface{ +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; + } + 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(A1(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 FunctionPointerInterface{ +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; + } + 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)(A1(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)->_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 FunctionPointerInterface{ + constexpr static const bool Internal = sizeof(F) <= sizeof(impl::FunctionPointerStorage); +public: + FunctorPointer(const F & f) + { + attach(f); + } + FunctorPointer(const FunctorPointer & fp) { + *this = fp; + } + template + typename std::enable_if::value>::type + attach(const 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(const A1&& a1) const{ + return const_ref()(A1(forward(a1))); + } + R (*get_function() const)(){ + return NULL; + } + operator bool() const { + return true; + } + bool operator ==(const FunctionPointerInterface & rhs) const { + return false; + } + FunctionPointerInterface & operator = (const FunctionPointerInterface & rhs) const { + return *this = *static_cast(&rhs); + } + FunctorPointer & operator = (const FunctorPointer & rhs) { + deallocate(); + attach(rhs.const_ref()); + return *this; + } + void copy_to(void * storage) const { + new(storage) FunctorPointer(*this); + } + ~FunctorPointer() { + deallocate(); + } + template + typename std::enable_if::value, const F &>::type + const_ref() const{ + 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._raw_storage); + } + template + typename std::enable_if::value>::type + deallocate() { + reinterpret_cast(this->_fp._raw_storage)->~F(); + } + + 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