diff --git a/include/fc/actor.hpp b/include/fc/actor.hpp new file mode 100644 index 0000000..558e951 --- /dev/null +++ b/include/fc/actor.hpp @@ -0,0 +1,46 @@ +#pragma once +#include +#include + +namespace fc { + + namespace detail { + struct actor_member { + // TODO: expand for all method arity and constness.... + template + static fc::function(A1)> functor( P&& p, R (C::*mem_func)(A1), fc::thread* t = nullptr) { + return [=](A1 a1){ return t->async( [=](){ return (p->*mem_func)(a1); } ); }; + } + }; + + template + struct actor_vtable_visitor { + template + actor_vtable_visitor( fc::thread* t, U&& u ):_thread(t),_this( fc::forward(u) ){} + + template + void operator()( const char* name, Function& memb, MemberPtr m )const { + memb = actor_member::functor( _this, m, _thread ); + } + fc::thread* _thread; + ThisPtr _this; + }; + } + + /** + * Posts all method calls to another thread and + * returns a future. + */ + template + class actor : public ptr { + public: + template + actor( InterfaceType* p, fc::thread* t = &fc::thread::current() ) + { + this->_vtable.reset(new detail::vtable() ); + this->_vtable->template visit( detail::actor_vtable_visitor(t, p) ); + } + + }; + +} // namespace fc diff --git a/include/fc/function.hpp b/include/fc/function.hpp index 153b64f..190a98b 100644 --- a/include/fc/function.hpp +++ b/include/fc/function.hpp @@ -1,50 +1,35 @@ -#ifndef _FC_FUNCTION_HPP_ -#define _FC_FUNCTION_HPP_ +#pragma once #include #include -/* -#include -#include namespace fc { - // place holder for more compile-effecient functor -#if !defined(BOOST_NO_TEMPLATE_ALIASES) - template - using function = std::function; -#else -#endif -*/ - - -//template -//class function { }; - -namespace fc { - template -class function_impl { +class function { public: + function(){} + template - function_impl( Functor&& f ) + function( Functor&& f ) :func( new impl( fc::forward(f) ) ){}; - function_impl( const function_impl& c ):func(c.func){} - function_impl( function_impl&& c ) { fc::swap( func, c.func); } - ~function_impl(){} + function( const function& c ):func(c.func){} + function( function&& c ) { fc::swap( func, c.func); } + ~function(){} template - function_impl& operator=( Functor&& f ) { + function& operator=( Functor&& f ) { func.reset( new impl( fc::forward(f) ) ); return *this; } - function_impl& operator=( const function_impl& c ) { func = c.func; return *this; } - function_impl& operator=( function_impl&& c ) { fc::swap(func,c.func); return *this; } + function& operator=( const function& c ) { func = c.func; return *this; } + function& operator=( function&& c ) { fc::swap(func,c.func); return *this; } template R operator()( Args2... args2) { return func->call(fc::forward(args2)...); } - private: + protected: + struct impl_base : public fc::retainable { virtual ~impl_base(){} virtual R call(Args...) = 0; @@ -59,6 +44,8 @@ class function_impl { Functor func; }; + function( const fc::shared_ptr& f ):func(f){} + function( fc::shared_ptr&& f ):func(fc::move(f)){} fc::shared_ptr func; }; @@ -71,44 +58,50 @@ class function_impl { * * TODO: Small functions are allocated on the stack, large functors are * allocated on the heap. + * + * Simply including boost/function adds an additional 0.6 seconds to every + * object file compared to using fc/function. + * + * Including on the other hand adds a mere 0.05 + * seconds to every object file compared to fc/function. */ -template -class function : public function_impl { - public: - template - function( U&& u ):function_impl( fc::forward(u) ){} - using function_impl::operator=; -}; - template -class function : public function_impl { +class function : public function { public: + function(){} template - function( U&& u ):function_impl( fc::forward(u) ){} - using function_impl::operator=; + function( U&& u ) { *this = fc::forward(u); } + using function::operator=; }; template -class function : public function_impl { +class function : public function { public: + function(){} template - function( U&& u ):function_impl( fc::forward(u) ){} - using function_impl::operator=; + function( U&& u ) { *this = fc::forward(u); } + //using function::operator=; }; template -class function : public function_impl { +class function : public function { public: + function(){} template - function( U&& u ):function_impl( fc::forward(u) ){} - using function_impl::operator=; + function( U&& u ):function( fc::forward(u) ){} + function( const function& c ):function(c.func){} + using function::operator=; }; - - - - +template +class function : public function { + public: + function(){} + template + function( U&& u ):function( fc::forward(u) ){} + function( const function& c ):function(c.func){} + using function::operator=; +}; } -#endif // _FC_FUNCTION_HPP_ diff --git a/include/fc/ptr.hpp b/include/fc/ptr.hpp new file mode 100644 index 0000000..c4cf4d0 --- /dev/null +++ b/include/fc/ptr.hpp @@ -0,0 +1,90 @@ +#pragma once +#include +#include + +namespace fc { + + namespace detail { + struct identity_member { + // TODO: enumerate all method patterns + template + static fc::function functor( P&& p, R (C::*mem_func)() ) { + return [=](){ return (p->*mem_func)(); }; + } + + template + static fc::function functor( P&& p, R (C::*mem_func)(A1) ) { + return [=](A1 a1){ return (p->*mem_func)(a1); }; + } + }; + + template< typename Interface, typename Transform = detail::identity_member > + struct vtable{}; + + template + struct vtable_visitor { + template + vtable_visitor( U&& u ):_this( fc::forward(u) ){} + + template + void operator()( const char* name, Function& memb, MemberPtr m )const { + memb = identity_member::functor( _this, m ); + } + ThisPtr _this; + }; + } // namespace detail + + template + class ptr { + public: + typedef detail::vtable vtable_type; + + ptr(){} + + template + ptr( InterfaceType* p ) + :_vtable( new vtable_type() ) { + _vtable->template visit( detail::vtable_visitor(p) ); + } + + template + ptr( const fc::shared_ptr& p ) + :_vtable( new vtable_type() ),_self(p){ + _vtable->template visit( detail::vtable_visitor(p.get()) ); + } + + vtable_type& operator*() { return *_vtable; } + const vtable_type& operator*()const { return *_vtable; } + + vtable_type* operator->() { return _vtable.get(); } + const vtable_type* operator->()const { return _vtable.get(); } + + protected: + fc::shared_ptr< vtable_type > _vtable; + fc::shared_ptr< fc::retainable > _self; + }; + + +} + +#include +#include + +#define FC_STUB_VTABLE_DEFINE_MEMBER( r, data, elem ) \ + decltype(Transform::functor( (data*)nullptr, &data::elem)) elem; +#define FC_STUB_VTABLE_DEFINE_VISIT( r, data, elem ) \ + v( BOOST_PP_STRINGIZE(elem), elem, &T::elem ); \ + +#define FC_STUB( CLASS, METHODS ) \ +namespace fc { namespace detail { \ + template \ + struct vtable : public fc::retainable { \ + BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_MEMBER, CLASS, METHODS ) \ + template \ + void visit( Visitor&& v ) { \ + BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_VISIT, CLASS, METHODS ) \ + } \ + }; \ +} } +//#undef FC_STUB_VTABLE_DEFINE_MEMBER +//#undef FC_STUB_VTABLE_DEFINE_VISIT