/*************************************************************************** * Copyright (C) 2008 by Gerd v. Egidy and Reinhard Pfau * * gve@intra2net.com * * * * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License version * * 2.1 as published by the Free Software Foundation. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef __LIBT2N_CLIENT_WRAPPER #define __LIBT2N_CLIENT_WRAPPER #include #include #include #include #include #include #include #include #ifndef T2NWRAPPER_MAX_ARGS #define T2NWRAPPER_MAX_ARGS 9 #endif namespace libt2n { class ConnectionInitData { public: virtual std::auto_ptr createConnection()=0; virtual ~ConnectionInitData() { } }; class TrivialHandler { public: static void handle( boost::function< void() > f) { f(); } }; // contains the internal stuff needed for T2nWrapper namespace detail { template< typename T > struct TypeWrap { typedef T type; }; template< > struct TypeWrap< void > { typedef int type; }; template< typename R > struct Call { typedef boost::function< R() > FuncType; FuncType function; R& result; Call( FuncType f, R& res ) : function(f), result( res ) {} void operator()() { result= function(); } }; template< > struct Call { typedef boost::function< void() > FuncType; typedef TypeWrap< void >::type ResultType; FuncType function; ResultType& result; Call( FuncType f, ResultType& res ) : function(f), result( res ) {} void operator()() { function(); result= ResultType(); } }; } // eo namespace detail template< class Client, class Handler = TrivialHandler > class T2nWrapper { private: std::auto_ptr conndConn; std::auto_ptr client; static std::auto_ptr singletonObject; static std::auto_ptr initData; // create a prep-method for each possible number of parameters #define _GEN_ARG(z,n,d) Arg ## n arg ##n #define _GEN_PREP(z,n,d) \ template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \ static boost::function< R(Client*) > prep \ ( \ R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \ BOOST_PP_COMMA_IF(n) \ BOOST_PP_ENUM( n, _GEN_ARG, ~ ) \ ) \ { \ return boost::bind< R > \ ( \ f, _1 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,arg) \ ); \ } // eo prep BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1) , _GEN_PREP, ~ ) #undef _GEN_PREP #undef _GEN_ARG static void ensureSingletonThere(void) { if (singletonObject.get() == NULL) { // we need to initialize if (initData.get() == NULL) throw std::logic_error("T2nWrapper singleton used before setting initData"); std::auto_ptr myConndConn=initData->createConnection(); } } template< typename R > static typename detail::TypeWrap::type real_exec( boost::function< R(Client*) > f) { ensureSingletonThere(); typename detail::TypeWrap::type result; detail::Call call( boost::bind( f, &(*(singletonObject->client))), result ); Handler::handle( call ); return result; } public: static void setInitData(std::auto_ptr newInitData) { initData=newInitData; } static ConnectionInitData* getInitData(void) { return initData.get(); } T2nWrapper() { client=std::auto_ptr(new Client(*conndConn)); } // create an exec-method for each possible number of parameters #define _GEN_PLACEHOLDER(z,n,d) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1)) #define _GEN_EXEC(z,n,d) \ template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \ static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > exec \ ( \ R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \ ) \ { \ boost::function(*p)(R(Client::*)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \ BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg)) \ = &T2nWrapper::template prep; \ return boost::bind \ ( \ T2nWrapper::template real_exec, \ boost::bind( p, f BOOST_PP_COMMA_IF(n) \ BOOST_PP_ENUM(n, _GEN_PLACEHOLDER, ~ ) ) \ ); \ } // eo exec BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ ) #undef _GEN_EXEC #undef _GEN_PLACEHOLDER }; } #endif