libt2n: (gerd) some progress with T2nWrapper (compiles but not complete yet)
[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
33#ifndef T2NWRAPPER_MAX_ARGS
34#define T2NWRAPPER_MAX_ARGS 9
35#endif
36
37namespace libt2n
38{
39
40class ConnectionInitData
41{
42 public:
43
44 virtual std::auto_ptr<client_connection> createConnection()=0;
45
46 virtual ~ConnectionInitData()
47 { }
48};
49
50class TrivialHandler
51{
52 public:
53 static void handle( boost::function< void() > f)
54 {
55 f();
56 }
57};
58
59// contains the internal stuff needed for T2nWrapper
60namespace detail
61{
62
63 template< typename T >
64 struct TypeWrap
65 {
66 typedef T type;
67 };
68
69 template< >
70 struct TypeWrap< void >
71 {
72 typedef int type;
73 };
74
75 template< typename R >
76 struct Call
77 {
78 typedef boost::function< R() > FuncType;
79
80 FuncType function;
81 R& result;
82
83 Call( FuncType f, R& res ) : function(f), result( res ) {}
84
85 void operator()()
86 {
87 result= function();
88 }
89 };
90
91 template< >
92 struct Call<void>
93 {
94 typedef boost::function< void() > FuncType;
95 typedef TypeWrap< void >::type ResultType;
96
97 FuncType function;
98 ResultType& result;
99
100 Call( FuncType f, ResultType& res ) : function(f), result( res ) {}
101
102 void operator()()
103 {
104 function();
105 result= ResultType();
106 }
107 };
108} // eo namespace detail
109
110template<
111 class Client,
112 class Handler = TrivialHandler
113>
114class T2nWrapper
115{
116 private:
117
118 std::auto_ptr<client_connection> conndConn;
119 std::auto_ptr<Client> client;
120
121 static std::auto_ptr<T2nWrapper> singletonObject;
122 static std::auto_ptr<ConnectionInitData> initData;
123
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 \
129 ( \
130 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
131 BOOST_PP_COMMA_IF(n) \
132 BOOST_PP_ENUM( n, _GEN_ARG, ~ ) \
133 ) \
134 { \
135 return boost::bind< R > \
136 ( \
137 f, _1 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,arg) \
138 ); \
139 } // eo prep
140
141 BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1) , _GEN_PREP, ~ )
142
143#undef _GEN_PREP
144#undef _GEN_ARG
145
146 static void ensureSingletonThere(void)
147 {
148 if (singletonObject.get() == NULL)
149 {
150 // we need to initialize
151
152 if (initData.get() == NULL)
153 throw std::logic_error("T2nWrapper singleton used before setting initData");
154
155 std::auto_ptr<client_connection> myConndConn=initData->createConnection();
156
157 }
158 }
159
160 template< typename R >
161 static
162 typename detail::TypeWrap<R>::type real_exec( boost::function< R(Client*) > f)
163 {
164 ensureSingletonThere();
165
166 typename detail::TypeWrap<R>::type result;
167 detail::Call<R> call( boost::bind( f, &(*(singletonObject->client))), result );
168 Handler::handle( call );
169 return result;
170 }
171
172 public:
173
174 static void setInitData(std::auto_ptr<ConnectionInitData> newInitData)
175 { initData=newInitData; }
176 static ConnectionInitData* getInitData(void)
177 { return initData.get(); }
178
179 T2nWrapper()
180 {
181 client=std::auto_ptr<Client>(new Client(*conndConn));
182 }
183
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 \
189 ( \
190 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
191 ) \
192 { \
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) >; \
196 return boost::bind \
197 ( \
198 T2nWrapper::template real_exec<R>, \
199 boost::bind( p, f BOOST_PP_COMMA_IF(n) \
200 BOOST_PP_ENUM(n, _GEN_PLACEHOLDER, ~ ) ) \
201 ); \
202 } // eo exec
203
204 BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
205
206#undef _GEN_EXEC
207#undef _GEN_PLACEHOLDER
208
209};
210
211}
212#endif