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/bind.hpp>
26 #include <boost/function.hpp>
27 #include <boost/preprocessor.hpp>
30 #include <command_client.hxx>
32 #ifndef T2N_SINGLETON_WRAPPER_MAX_ARGS
33 #define T2N_SINGLETON_WRAPPER_MAX_ARGS 9
39 class ConnectionWrapper
43 virtual client_connection* get_connection()=0;
45 virtual long long get_command_timeout_usec(void)
47 return command_client::command_timeout_usec_default;
50 virtual long long get_hello_timeout_usec(void)
52 return command_client::hello_timeout_usec_default;
55 virtual void handle(command_client* stubBase, boost::function< void() > f)
60 virtual ~ConnectionWrapper()
64 // contains the internal stuff needed for T2nWrapper
68 template< typename T >
75 struct TypeWrap< void >
80 template< typename R >
83 typedef boost::function< R() > FuncType;
88 Call( FuncType f, R& res ) : function(f), result( res ) {}
99 typedef boost::function< void() > FuncType;
100 typedef TypeWrap< void >::type ResultType;
105 Call( FuncType f, ResultType& res ) : function(f), result( res ) {}
110 result= ResultType();
113 } // eo namespace detail
115 class T2nSingletonWrapperMessages
118 static const char* NotInitializedMessage;
121 template< class Client >
122 class T2nSingletonWrapper : public T2nSingletonWrapperMessages
125 std::auto_ptr<Client> Stub;
127 static std::auto_ptr<T2nSingletonWrapper> SingletonObject;
128 static std::auto_ptr<ConnectionWrapper> WrappedConnection;
130 // create a prep-method for each possible number of parameters
131 #define _GEN_ARG(z,n,d) Arg ## n arg ##n
132 #define _GEN_PREP(z,n,d) \
133 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
134 static boost::function< R(Client*) > prep \
136 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
137 BOOST_PP_COMMA_IF(n) \
138 BOOST_PP_ENUM( n, _GEN_ARG, ~ ) \
141 return boost::bind< R > \
143 f, _1 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,arg) \
147 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1) , _GEN_PREP, ~ )
152 T2nSingletonWrapper(std::auto_ptr<Client> stub)
159 if (WrappedConnection.get() == NULL)
160 throw std::logic_error(NotInitializedMessage);
162 std::auto_ptr<Client> stub(new Client(*(WrappedConnection->get_connection()),
163 WrappedConnection->get_command_timeout_usec(),
164 WrappedConnection->get_hello_timeout_usec()));
166 SingletonObject=std::auto_ptr<T2nSingletonWrapper>(new T2nSingletonWrapper(stub));
169 template< typename R >
171 typename detail::TypeWrap<R>::type real_exec( boost::function< R(Client*) > f)
173 ensure_singleton_there();
175 typename detail::TypeWrap<R>::type result;
176 detail::Call<R> call( boost::bind( f, SingletonObject->Stub.get()), result );
177 WrappedConnection->handle(SingletonObject->Stub.get(),call);
183 static void set_connection(std::auto_ptr<ConnectionWrapper> wrappedConnection)
185 WrappedConnection=wrappedConnection;
187 // reset the singleton to NULL because the singleton must be constructed with current WrappedConnection
188 if (SingletonObject.get() != NULL)
189 SingletonObject.reset();
191 static ConnectionWrapper* get_connection(void)
192 { return WrappedConnection.get(); }
194 static void ensure_singleton_there(void)
196 if (SingletonObject.get() == NULL)
200 // create an exec-method for each possible number of parameters
201 #define _GEN_PLACEHOLDER(z,n,d) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1))
202 #define _GEN_EXEC(z,n,d) \
203 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
204 static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > exec \
206 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
209 boost::function<R(Client*)>(*p)(R(Client::*)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
210 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg)) \
211 = &T2nSingletonWrapper::template prep<R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg) >; \
214 T2nSingletonWrapper::template real_exec<R>, \
215 boost::bind( p, f BOOST_PP_COMMA_IF(n) \
216 BOOST_PP_ENUM(n, _GEN_PLACEHOLDER, ~ ) ) \
220 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
223 #undef _GEN_PLACEHOLDER
227 // create an t2n_exec-method for each possible number of parameters
228 #define _GEN_EXEC(z,n,d) \
229 template< class Client, typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
230 static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > t2n_exec \
232 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
235 return T2nSingletonWrapper<Client>::exec(f); \
238 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
241 #undef _GEN_PLACEHOLDER