/* * Copyright (c) 2014, Siemens AG. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef EMBB_BASE_INTERNAL_FUNCTION0_H_ #define EMBB_BASE_INTERNAL_FUNCTION0_H_ #include #include #include #include #include #include namespace embb { namespace base { namespace internal { template class Function0 { public: virtual ~Function0() {} virtual R operator () () = 0; virtual void CopyTo(void* dst) = 0; }; template class FunctionPointer0 : public Function0 { public: typedef R(*FuncPtrType)(); explicit FunctionPointer0(FuncPtrType func) : function_(func) {} virtual R operator () () { return function_(); } virtual void CopyTo(void* dst) { new(dst)FunctionPointer0(function_); } private: FuncPtrType function_; }; template <> class FunctionPointer0 : public Function0 { public: typedef void(*FuncPtrType)(); explicit FunctionPointer0(FuncPtrType func) : function_(func) {} virtual void operator () () { function_(); } virtual void CopyTo(void* dst) { new(dst)FunctionPointer0(function_); } private: FuncPtrType function_; }; template class MemberFunctionPointer0 : public Function0 { public: typedef R(C::*MemFuncPtrType)(); typedef C & ClassRefType; MemberFunctionPointer0(ClassRefType obj, MemFuncPtrType func) : object_(obj), function_(func) {} explicit MemberFunctionPointer0(ClassRefType obj) : object_(obj), function_(&C::operator()) {} void operator = (MemberFunctionPointer0 const & memfunc) { object_ = memfunc.object_; function_ = memfunc.function_; } virtual R operator () () { return (object_.*function_)(); } virtual void CopyTo(void* dst) { new(dst)MemberFunctionPointer0(object_, function_); } private: ClassRefType object_; MemFuncPtrType function_; }; template class MemberFunctionPointer0 : public Function0 { public: typedef void(C::*MemFuncPtrType)(); typedef C & ClassRefType; MemberFunctionPointer0(ClassRefType obj, MemFuncPtrType func) : object_(obj), function_(func) {} explicit MemberFunctionPointer0(ClassRefType obj) : object_(obj), function_(&C::operator()) {} void operator = (MemberFunctionPointer0 const & memfunc) { object_ = memfunc.object_; function_ = memfunc.function_; } virtual void operator () () { (object_.*function_)(); } virtual void CopyTo(void* dst) { new(dst)MemberFunctionPointer0(object_, function_); } private: ClassRefType object_; MemFuncPtrType function_; }; template class FunctorWrapper0 : public Function0 { public: FunctorWrapper0() : object_(NULL), ref_count_(NULL) {} explicit FunctorWrapper0(C const & obj) { object_ = Allocation::New(obj); ref_count_ = Allocation::New >(1); } explicit FunctorWrapper0(FunctorWrapper0 const & other) { object_ = other.object_; ref_count_ = other.ref_count_; ++*ref_count_; } virtual ~FunctorWrapper0() { if (0 == --*ref_count_) { Allocation::Delete(ref_count_); Allocation::Delete(object_); } } virtual R operator () () { return (*object_)(); } virtual void CopyTo(void* dst) { new(dst)FunctorWrapper0(*this); } private: C * object_; Atomic * ref_count_; }; template class FunctorWrapper0 : public Function0 { public: FunctorWrapper0() : object_(NULL), ref_count_(NULL) {} explicit FunctorWrapper0(C const & obj) { object_ = Allocation::New(obj); ref_count_ = Allocation::New >(1); } explicit FunctorWrapper0(FunctorWrapper0 const & other) { object_ = other.object_; ref_count_ = other.ref_count_; ++*ref_count_; } virtual ~FunctorWrapper0() { if (0 == --*ref_count_) { Allocation::Delete(ref_count_); Allocation::Delete(object_); } } virtual void operator () () { (*object_)(); } virtual void CopyTo(void* dst) { new(dst)FunctorWrapper0(*this); } private: C * object_; Atomic * ref_count_; }; } // namespace internal using embb::base::internal::Nil; template class Function { public: typedef internal::Function0 * FuncPtrType; Function() : function_(NULL) {} template explicit Function(C const & obj) { function_ = new(storage_) internal::FunctorWrapper0(obj); } Function(Function const & func) { func.function_->CopyTo(&storage_[0]); function_ = reinterpret_cast(&storage_[0]); } ~Function() { Free(); } void operator = (R(*func)()) { Free(); function_ = new(storage_) internal::FunctionPointer0(func); } void operator = (Function & func) { Free(); func.function_->CopyTo(&storage_[0]); function_ = reinterpret_cast(&storage_[0]); } template void operator = (C const & obj) { Free(); function_ = new(storage_) internal::FunctorWrapper0(obj); } explicit Function(R(*func)()) { function_ = new(storage_) internal::FunctionPointer0(func); } template Function(C & obj, R(C::*func)()) { function_ = new(storage_) internal::MemberFunctionPointer0(obj, func); } R operator () () { return (*function_)(); } private: char storage_[sizeof( internal::MemberFunctionPointer0)]; FuncPtrType function_; void Free() { if (NULL != function_) { function_->~Function0(); function_ = NULL; } } }; // wrap member function template Function MakeFunction(C & obj, R(C::*func)()) { return Function(obj, func); } // wrap function pointer template Function MakeFunction( R(*func)()) { return Function(func); } // bind to Function0 template Function Bind( C & obj, R(C::*func)()) { return Function(obj, func); } template Function Bind( R(*func)()) { return Function(func); } } // namespace base } // namespace embb #endif // EMBB_BASE_INTERNAL_FUNCTION0_H_