Implemented basic mace::stub with fast compiles!!
This commit is contained in:
parent
d36d7f8bc9
commit
4aad422411
3 changed files with 179 additions and 50 deletions
46
include/fc/actor.hpp
Normal file
46
include/fc/actor.hpp
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fc/ptr.hpp>
|
||||||
|
#include <fc/thread.hpp>
|
||||||
|
|
||||||
|
namespace fc {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
struct actor_member {
|
||||||
|
// TODO: expand for all method arity and constness....
|
||||||
|
template<typename R, typename C, typename A1, typename P>
|
||||||
|
static fc::function<fc::future<R>(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<typename ThisPtr>
|
||||||
|
struct actor_vtable_visitor {
|
||||||
|
template<typename U>
|
||||||
|
actor_vtable_visitor( fc::thread* t, U&& u ):_thread(t),_this( fc::forward<U>(u) ){}
|
||||||
|
|
||||||
|
template<typename Function, typename MemberPtr>
|
||||||
|
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<typename Interface>
|
||||||
|
class actor : public ptr<Interface, detail::actor_member> {
|
||||||
|
public:
|
||||||
|
template<typename InterfaceType>
|
||||||
|
actor( InterfaceType* p, fc::thread* t = &fc::thread::current() )
|
||||||
|
{
|
||||||
|
this->_vtable.reset(new detail::vtable<Interface,detail::actor_member>() );
|
||||||
|
this->_vtable->template visit<InterfaceType>( detail::actor_vtable_visitor<InterfaceType*>(t, p) );
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fc
|
||||||
|
|
@ -1,50 +1,35 @@
|
||||||
#ifndef _FC_FUNCTION_HPP_
|
#pragma once
|
||||||
#define _FC_FUNCTION_HPP_
|
|
||||||
#include <fc/utility.hpp>
|
#include <fc/utility.hpp>
|
||||||
#include <fc/shared_ptr.hpp>
|
#include <fc/shared_ptr.hpp>
|
||||||
/*
|
|
||||||
#include <functional>
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
// place holder for more compile-effecient functor
|
|
||||||
#if !defined(BOOST_NO_TEMPLATE_ALIASES)
|
|
||||||
template<typename T>
|
|
||||||
using function = std::function<T>;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//template<typename Signature>
|
|
||||||
//class function { };
|
|
||||||
|
|
||||||
namespace fc {
|
|
||||||
|
|
||||||
template<typename R,typename ... Args>
|
template<typename R,typename ... Args>
|
||||||
class function_impl {
|
class function {
|
||||||
public:
|
public:
|
||||||
|
function(){}
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
function_impl( Functor&& f )
|
function( Functor&& f )
|
||||||
:func( new impl<Functor>( fc::forward<Functor>(f) ) ){};
|
:func( new impl<Functor>( fc::forward<Functor>(f) ) ){};
|
||||||
|
|
||||||
function_impl( const function_impl& c ):func(c.func){}
|
function( const function& c ):func(c.func){}
|
||||||
function_impl( function_impl&& c ) { fc::swap( func, c.func); }
|
function( function&& c ) { fc::swap( func, c.func); }
|
||||||
~function_impl(){}
|
~function(){}
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
function_impl& operator=( Functor&& f ) {
|
function& operator=( Functor&& f ) {
|
||||||
func.reset( new impl<Functor>( fc::forward<Functor>(f) ) );
|
func.reset( new impl<Functor>( fc::forward<Functor>(f) ) );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
function_impl& operator=( const function_impl& c ) { func = c.func; return *this; }
|
function& operator=( const function& c ) { func = c.func; return *this; }
|
||||||
function_impl& operator=( function_impl&& c ) { fc::swap(func,c.func); return *this; }
|
function& operator=( function&& c ) { fc::swap(func,c.func); return *this; }
|
||||||
|
|
||||||
template<typename... Args2>
|
template<typename... Args2>
|
||||||
R operator()( Args2... args2) { return func->call(fc::forward<Args2>(args2)...); }
|
R operator()( Args2... args2) { return func->call(fc::forward<Args2>(args2)...); }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
struct impl_base : public fc::retainable {
|
struct impl_base : public fc::retainable {
|
||||||
virtual ~impl_base(){}
|
virtual ~impl_base(){}
|
||||||
virtual R call(Args...) = 0;
|
virtual R call(Args...) = 0;
|
||||||
|
|
@ -59,6 +44,8 @@ class function_impl {
|
||||||
|
|
||||||
Functor func;
|
Functor func;
|
||||||
};
|
};
|
||||||
|
function( const fc::shared_ptr<impl_base>& f ):func(f){}
|
||||||
|
function( fc::shared_ptr<impl_base>&& f ):func(fc::move(f)){}
|
||||||
|
|
||||||
fc::shared_ptr<impl_base> func;
|
fc::shared_ptr<impl_base> func;
|
||||||
};
|
};
|
||||||
|
|
@ -71,44 +58,50 @@ class function_impl {
|
||||||
*
|
*
|
||||||
* TODO: Small functions are allocated on the stack, large functors are
|
* TODO: Small functions are allocated on the stack, large functors are
|
||||||
* allocated on the heap.
|
* allocated on the heap.
|
||||||
|
*
|
||||||
|
* Simply including boost/function adds an additional 0.6 seconds to every
|
||||||
|
* object file compared to using fc/function.
|
||||||
|
*
|
||||||
|
* Including <functional> on the other hand adds a mere 0.05
|
||||||
|
* seconds to every object file compared to fc/function.
|
||||||
*/
|
*/
|
||||||
template<typename Signature = void()>
|
|
||||||
class function : public function_impl<void> {
|
|
||||||
public:
|
|
||||||
template<typename U>
|
|
||||||
function( U&& u ):function_impl<void>( fc::forward<U>(u) ){}
|
|
||||||
using function_impl::operator=;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
class function<R()> : public function_impl<R> {
|
class function<R()> : public function<R> {
|
||||||
public:
|
public:
|
||||||
|
function(){}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
function( U&& u ):function_impl<R>( fc::forward<U>(u) ){}
|
function( U&& u ) { *this = fc::forward<U>(u); }
|
||||||
using function_impl<R>::operator=;
|
using function<R>::operator=;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename R,typename A1>
|
template<typename R,typename A1>
|
||||||
class function<R(A1)> : public function_impl<R,A1> {
|
class function<R(A1)> : public function<R,A1> {
|
||||||
public:
|
public:
|
||||||
|
function(){}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
function( U&& u ):function_impl<R,A1>( fc::forward<U>(u) ){}
|
function( U&& u ) { *this = fc::forward<U>(u); }
|
||||||
using function_impl<R,A1>::operator=;
|
//using function<R,A1>::operator=;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename R,typename A1,typename A2>
|
template<typename R,typename A1,typename A2>
|
||||||
class function<R(A1,A2)> : public function_impl<R,A1,A2> {
|
class function<R(A1,A2)> : public function<R,A1,A2> {
|
||||||
public:
|
public:
|
||||||
|
function(){}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
function( U&& u ):function_impl<R,A1,A2>( fc::forward<U>(u) ){}
|
function( U&& u ):function<R,A1,A2>( fc::forward<U>(u) ){}
|
||||||
using function_impl<R,A1,A2>::operator=;
|
function( const function& c ):function<R,A1,A2>(c.func){}
|
||||||
|
using function<R,A1,A2>::operator=;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename R,typename A1,typename A2, typename A3>
|
||||||
|
class function<R(A1,A2,A3)> : public function<R,A1,A2,A3> {
|
||||||
|
public:
|
||||||
|
function(){}
|
||||||
|
template<typename U>
|
||||||
|
function( U&& u ):function<R,A1,A2,A3>( fc::forward<U>(u) ){}
|
||||||
|
function( const function& c ):function<R,A1,A2,A3>(c.func){}
|
||||||
|
using function<R,A1,A2,A3>::operator=;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _FC_FUNCTION_HPP_
|
|
||||||
|
|
|
||||||
90
include/fc/ptr.hpp
Normal file
90
include/fc/ptr.hpp
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fc/function.hpp>
|
||||||
|
#include <fc/future.hpp>
|
||||||
|
|
||||||
|
namespace fc {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
struct identity_member {
|
||||||
|
// TODO: enumerate all method patterns
|
||||||
|
template<typename R, typename C, typename P>
|
||||||
|
static fc::function<R()> functor( P&& p, R (C::*mem_func)() ) {
|
||||||
|
return [=](){ return (p->*mem_func)(); };
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R, typename C, typename A1, typename P>
|
||||||
|
static fc::function<R(A1)> 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<typename ThisPtr>
|
||||||
|
struct vtable_visitor {
|
||||||
|
template<typename U>
|
||||||
|
vtable_visitor( U&& u ):_this( fc::forward<U>(u) ){}
|
||||||
|
|
||||||
|
template<typename Function, typename MemberPtr>
|
||||||
|
void operator()( const char* name, Function& memb, MemberPtr m )const {
|
||||||
|
memb = identity_member::functor( _this, m );
|
||||||
|
}
|
||||||
|
ThisPtr _this;
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename Interface, typename Transform = detail::identity_member >
|
||||||
|
class ptr {
|
||||||
|
public:
|
||||||
|
typedef detail::vtable<Interface,Transform> vtable_type;
|
||||||
|
|
||||||
|
ptr(){}
|
||||||
|
|
||||||
|
template<typename InterfaceType>
|
||||||
|
ptr( InterfaceType* p )
|
||||||
|
:_vtable( new vtable_type() ) {
|
||||||
|
_vtable->template visit<InterfaceType>( detail::vtable_visitor<InterfaceType*>(p) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename InterfaceType>
|
||||||
|
ptr( const fc::shared_ptr<InterfaceType>& p )
|
||||||
|
:_vtable( new vtable_type() ),_self(p){
|
||||||
|
_vtable->template visit<InterfaceType>( detail::vtable_visitor<InterfaceType*>(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 <boost/preprocessor/seq/for_each.hpp>
|
||||||
|
#include <boost/preprocessor/stringize.hpp>
|
||||||
|
|
||||||
|
#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<typename Transform> \
|
||||||
|
struct vtable<test,Transform> : public fc::retainable { \
|
||||||
|
BOOST_PP_SEQ_FOR_EACH( FC_STUB_VTABLE_DEFINE_MEMBER, CLASS, METHODS ) \
|
||||||
|
template<typename T, typename Visitor> \
|
||||||
|
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
|
||||||
Loading…
Reference in a new issue