libt2n: (tomj) make compilable again
[libt2n] / src / client_wrapper.hxx
CommitLineData
45508d07
GE
1/***************************************************************************
2 * Copyright (C) 2008 by Gerd v. Egidy and Reinhard Pfau *
3 * gve@intra2net.com *
4 * *
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. *
8 * *
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. *
13 * *
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
21
22#include <functional>
23
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>
29
30#include <client.hxx>
31#include <command_client.hxx>
32
0ea6d528
GE
33#ifndef T2N_SINGLETON_WRAPPER_MAX_ARGS
34#define T2N_SINGLETON_WRAPPER_MAX_ARGS 9
45508d07
GE
35#endif
36
37namespace libt2n
38{
39
0ea6d528 40class ConnectionWrapper
45508d07
GE
41{
42 public:
43
0ea6d528 44 virtual client_connection* get_connection()=0;
45508d07 45
0ea6d528
GE
46 virtual long long get_command_timeout_usec(void)
47 {
48 return command_client::command_timeout_usec_default;
49 }
45508d07 50
0ea6d528
GE
51 virtual long long get_hello_timeout_usec(void)
52 {
53 return command_client::hello_timeout_usec_default;
54 }
55
56 virtual void handle(command_client* stubBase, boost::function< void() > f)
45508d07
GE
57 {
58 f();
59 }
0ea6d528
GE
60
61 virtual ~ConnectionWrapper()
62 { }
45508d07
GE
63};
64
65// contains the internal stuff needed for T2nWrapper
66namespace detail
67{
68
69 template< typename T >
70 struct TypeWrap
71 {
72 typedef T type;
73 };
74
75 template< >
76 struct TypeWrap< void >
77 {
78 typedef int type;
79 };
80
81 template< typename R >
82 struct Call
83 {
84 typedef boost::function< R() > FuncType;
85
86 FuncType function;
87 R& result;
88
89 Call( FuncType f, R& res ) : function(f), result( res ) {}
90
91 void operator()()
92 {
93 result= function();
94 }
95 };
96
97 template< >
98 struct Call<void>
99 {
100 typedef boost::function< void() > FuncType;
101 typedef TypeWrap< void >::type ResultType;
102
103 FuncType function;
104 ResultType& result;
105
106 Call( FuncType f, ResultType& res ) : function(f), result( res ) {}
107
108 void operator()()
109 {
110 function();
111 result= ResultType();
112 }
113 };
114} // eo namespace detail
115
0ea6d528 116class T2nSingletonWrapperMessages
45508d07 117{
0ea6d528
GE
118 protected:
119 static const char* NotInitializedMessage;
120};
45508d07 121
0ea6d528
GE
122template< class Client >
123class T2nSingletonWrapper : public T2nSingletonWrapperMessages
124{
125 private:
126 std::auto_ptr<Client> Stub;
45508d07 127
0ea6d528
GE
128 static std::auto_ptr<T2nSingletonWrapper> SingletonObject;
129 static std::auto_ptr<ConnectionWrapper> WrappedConnection;
45508d07
GE
130
131 // create a prep-method for each possible number of parameters
132#define _GEN_ARG(z,n,d) Arg ## n arg ##n
133#define _GEN_PREP(z,n,d) \
134 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
135 static boost::function< R(Client*) > prep \
136 ( \
137 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
138 BOOST_PP_COMMA_IF(n) \
139 BOOST_PP_ENUM( n, _GEN_ARG, ~ ) \
140 ) \
141 { \
142 return boost::bind< R > \
143 ( \
144 f, _1 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,arg) \
145 ); \
146 } // eo prep
147
0ea6d528 148 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1) , _GEN_PREP, ~ )
45508d07
GE
149
150#undef _GEN_PREP
151#undef _GEN_ARG
152
a64066eb
GE
153 T2nSingletonWrapper(std::auto_ptr<Client> stub)
154 {
155 Stub=stub;
156 }
157
158 static void init()
45508d07 159 {
0ea6d528
GE
160 if (WrappedConnection.get() == NULL)
161 throw std::logic_error(NotInitializedMessage);
45508d07 162
a64066eb 163 std::auto_ptr<Client> stub(new Client(*(WrappedConnection->get_connection()),
0ea6d528
GE
164 WrappedConnection->get_command_timeout_usec(),
165 WrappedConnection->get_hello_timeout_usec()));
a64066eb
GE
166
167 SingletonObject=std::auto_ptr<T2nSingletonWrapper>(new T2nSingletonWrapper(stub));
45508d07
GE
168 }
169
170 template< typename R >
171 static
172 typename detail::TypeWrap<R>::type real_exec( boost::function< R(Client*) > f)
173 {
0ea6d528 174 ensure_singleton_there();
45508d07
GE
175
176 typename detail::TypeWrap<R>::type result;
0ea6d528
GE
177 detail::Call<R> call( boost::bind( f, SingletonObject->Stub.get()), result );
178 WrappedConnection->handle(SingletonObject->Stub.get(),call);
45508d07
GE
179 return result;
180 }
181
182 public:
183
0ea6d528
GE
184 static void set_connection(std::auto_ptr<ConnectionWrapper> wrappedConnection)
185 {
186 WrappedConnection=wrappedConnection;
187
188 // reset the singleton to NULL because the singleton must be constructed with current WrappedConnection
189 if (SingletonObject.get() != NULL)
190 SingletonObject.reset();
191 }
192 static ConnectionWrapper* get_connection(void)
193 { return WrappedConnection.get(); }
45508d07 194
0ea6d528 195 static void ensure_singleton_there(void)
45508d07 196 {
0ea6d528 197 if (SingletonObject.get() == NULL)
a64066eb 198 init();
45508d07
GE
199 }
200
201 // create an exec-method for each possible number of parameters
202#define _GEN_PLACEHOLDER(z,n,d) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1))
203#define _GEN_EXEC(z,n,d) \
204 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
205 static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > exec \
206 ( \
207 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
208 ) \
209 { \
210 boost::function<R(Client*)>(*p)(R(Client::*)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
211 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg)) \
0ea6d528 212 = &T2nSingletonWrapper::template prep<R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg) >; \
45508d07
GE
213 return boost::bind \
214 ( \
0ea6d528 215 T2nSingletonWrapper::template real_exec<R>, \
45508d07
GE
216 boost::bind( p, f BOOST_PP_COMMA_IF(n) \
217 BOOST_PP_ENUM(n, _GEN_PLACEHOLDER, ~ ) ) \
218 ); \
219 } // eo exec
220
0ea6d528 221 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
45508d07
GE
222
223#undef _GEN_EXEC
224#undef _GEN_PLACEHOLDER
225
226};
227
0ea6d528
GE
228// create an t2n_exec-method for each possible number of parameters
229#define _GEN_EXEC(z,n,d) \
230 template< class Client, typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
231 static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > t2n_exec \
232 ( \
233 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
234 ) \
235 { \
236 return T2nSingletonWrapper<Client>::exec(f); \
237 } // eo exec
238
239 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
240
241#undef _GEN_EXEC
242#undef _GEN_PLACEHOLDER
243
45508d07
GE
244}
245#endif