1 /***************************************************************************
2 * Copyright (C) 2008 by Gerd v. Egidy and Reinhard Pfau *
5 * This library is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU Lesser General Public License version *
7 * 2.1 as published by the Free Software Foundation. *
9 * This library is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19 #ifndef __LIBT2N_CLIENT_WRAPPER
20 #define __LIBT2N_CLIENT_WRAPPER
24 #include <boost/config.hpp>
25 #include <boost/any.hpp>
26 #include <boost/bind.hpp>
27 #include <boost/function.hpp>
28 #include <boost/preprocessor.hpp>
31 #include <command_client.hxx>
33 #ifndef T2NWRAPPER_MAX_ARGS
34 #define T2NWRAPPER_MAX_ARGS 9
40 class ConnectionInitData
44 virtual std::auto_ptr<client_connection> createConnection()=0;
46 virtual ~ConnectionInitData()
53 static void handle( boost::function< void() > f)
59 // contains the internal stuff needed for T2nWrapper
63 template< typename T >
70 struct TypeWrap< void >
75 template< typename R >
78 typedef boost::function< R() > FuncType;
83 Call( FuncType f, R& res ) : function(f), result( res ) {}
94 typedef boost::function< void() > FuncType;
95 typedef TypeWrap< void >::type ResultType;
100 Call( FuncType f, ResultType& res ) : function(f), result( res ) {}
105 result= ResultType();
108 } // eo namespace detail
112 class Handler = TrivialHandler
118 std::auto_ptr<client_connection> conndConn;
119 std::auto_ptr<Client> client;
121 static std::auto_ptr<T2nWrapper> singletonObject;
122 static std::auto_ptr<ConnectionInitData> initData;
124 // create a prep-method for each possible number of parameters
125 #define _GEN_ARG(z,n,d) Arg ## n arg ##n
126 #define _GEN_PREP(z,n,d) \
127 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
128 static boost::function< R(Client*) > prep \
130 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
131 BOOST_PP_COMMA_IF(n) \
132 BOOST_PP_ENUM( n, _GEN_ARG, ~ ) \
135 return boost::bind< R > \
137 f, _1 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,arg) \
141 BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1) , _GEN_PREP, ~ )
146 static void ensureSingletonThere(void)
148 if (singletonObject.get() == NULL)
150 // we need to initialize
152 if (initData.get() == NULL)
153 throw std::logic_error("T2nWrapper singleton used before setting initData");
155 std::auto_ptr<client_connection> myConndConn=initData->createConnection();
160 template< typename R >
162 typename detail::TypeWrap<R>::type real_exec( boost::function< R(Client*) > f)
164 ensureSingletonThere();
166 typename detail::TypeWrap<R>::type result;
167 detail::Call<R> call( boost::bind( f, &(*(singletonObject->client))), result );
168 Handler::handle( call );
174 static void setInitData(std::auto_ptr<ConnectionInitData> newInitData)
175 { initData=newInitData; }
176 static ConnectionInitData* getInitData(void)
177 { return initData.get(); }
181 client=std::auto_ptr<Client>(new Client(*conndConn));
184 // create an exec-method for each possible number of parameters
185 #define _GEN_PLACEHOLDER(z,n,d) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1))
186 #define _GEN_EXEC(z,n,d) \
187 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
188 static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > exec \
190 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
193 boost::function<R(Client*)>(*p)(R(Client::*)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
194 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg)) \
195 = &T2nWrapper::template prep<R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg) >; \
198 T2nWrapper::template real_exec<R>, \
199 boost::bind( p, f BOOST_PP_COMMA_IF(n) \
200 BOOST_PP_ENUM(n, _GEN_PLACEHOLDER, ~ ) ) \
204 BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
207 #undef _GEN_PLACEHOLDER