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