00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef __LIBT2N_CLIENT_WRAPPER
00023 #define __LIBT2N_CLIENT_WRAPPER
00024
00025 #include <functional>
00026
00027 #include <boost/config.hpp>
00028 #include <boost/bind.hpp>
00029 #include <boost/function.hpp>
00030 #include <boost/preprocessor.hpp>
00031
00032 #include <client.hxx>
00033 #include <command_client.hxx>
00034
00035 #ifndef T2N_SINGLETON_WRAPPER_MAX_ARGS
00036 #define T2N_SINGLETON_WRAPPER_MAX_ARGS 9
00037 #endif
00038
00039 namespace libt2n
00040 {
00041
00048 class ConnectionWrapper
00049 {
00050 private:
00051 long long command_timeout_usec;
00052 long long hello_timeout_usec;
00053
00054 protected:
00055 log_level_values log_level;
00056 std::ostream *logstream;
00057 void set_logging_on_connection(client_connection& c);
00058
00059 public:
00060 ConnectionWrapper()
00061 : command_timeout_usec(command_client::command_timeout_usec_default),
00062 hello_timeout_usec(command_client::hello_timeout_usec_default),
00063 log_level(none),
00064 logstream(NULL)
00065 { }
00066
00067 virtual ~ConnectionWrapper()
00068 { }
00069
00077 virtual client_connection* get_connection()=0;
00078
00090 virtual bool handle(command_client* stubBase, boost::function< void() > f)
00091 {
00092 f();
00093 return true;
00094 }
00095
00096 long long get_command_timeout_usec(void)
00097 { return command_timeout_usec; }
00098
00099 void set_command_timeout_usec(long long _command_timeout_usec)
00100 { command_timeout_usec=_command_timeout_usec; }
00101
00102 long long get_hello_timeout_usec(void)
00103 { return hello_timeout_usec; }
00104
00105 void set_hello_timeout_usec(long long _hello_timeout_usec)
00106 { hello_timeout_usec=_hello_timeout_usec; }
00107
00108 virtual void set_logging(std::ostream *_logstream, log_level_values _log_level);
00109
00110 std::ostream* get_logstream(log_level_values level);
00111 };
00112
00113
00114 namespace detail
00115 {
00116
00117 template< typename T >
00118 struct TypeWrap
00119 {
00120 typedef T type;
00121 };
00122
00123 template< >
00124 struct TypeWrap< void >
00125 {
00126 typedef int type;
00127 };
00128
00129 template< typename R >
00130 struct Call
00131 {
00132 typedef boost::function< R() > FuncType;
00133
00134 FuncType function;
00135 R& result;
00136
00137 Call( FuncType f, R& res ) : function(f), result( res ) {}
00138
00139 void operator()()
00140 {
00141 result= function();
00142 }
00143 };
00144
00145 template< >
00146 struct Call<void>
00147 {
00148 typedef boost::function< void() > FuncType;
00149 typedef TypeWrap< void >::type ResultType;
00150
00151 FuncType function;
00152 ResultType& result;
00153
00154 Call( FuncType f, ResultType& res ) : function(f), result( res ) {}
00155
00156 void operator()()
00157 {
00158 function();
00159 result= ResultType();
00160 }
00161 };
00162 }
00163
00164 class T2nSingletonWrapperMessages
00165 {
00166 protected:
00167 static const char* NotInitializedMessage;
00168 };
00169
00184 template< class Client >
00185 class T2nSingletonWrapper : public T2nSingletonWrapperMessages
00186 {
00187 private:
00188 std::auto_ptr<Client> Stub;
00189
00190 static std::auto_ptr<T2nSingletonWrapper> SingletonObject;
00191 static std::auto_ptr<ConnectionWrapper> WrappedConnection;
00192
00194
00195 #define _GEN_ARG(z,n,d) Arg ## n arg ##n
00196 #define _GEN_PREP(z,n,d) \
00197 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
00198 static boost::function< R(Client*) > prep \
00199 ( \
00200 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
00201 BOOST_PP_COMMA_IF(n) \
00202 BOOST_PP_ENUM( n, _GEN_ARG, ~ ) \
00203 ) \
00204 { \
00205 return boost::bind< R > \
00206 ( \
00207 f, _1 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,arg) \
00208 ); \
00209 } // eo prep
00210
00211 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1) , _GEN_PREP, ~ )
00212
00213 #undef _GEN_PREP
00214 #undef _GEN_ARG
00216
00217 T2nSingletonWrapper(std::auto_ptr<Client> stub)
00218 {
00219 Stub=stub;
00220 }
00221
00222 static void init()
00223 {
00224 if (WrappedConnection.get() == NULL)
00225 throw std::logic_error(NotInitializedMessage);
00226
00227 std::auto_ptr<Client> stub(new Client(WrappedConnection->get_connection(),
00228 WrappedConnection->get_command_timeout_usec(),
00229 WrappedConnection->get_hello_timeout_usec()));
00230
00231 SingletonObject=std::auto_ptr<T2nSingletonWrapper>(new T2nSingletonWrapper(stub));
00232 }
00233
00234 template< typename R >
00235 static
00236 typename detail::TypeWrap<R>::type real_exec( boost::function< R(Client*) > f)
00237 {
00238 ensure_singleton_there();
00239
00240 typename detail::TypeWrap<R>::type result;
00241
00242
00243 detail::Call<R> call( boost::bind( f, SingletonObject->Stub.get()), result );
00244
00245
00246 if (!WrappedConnection->handle(SingletonObject->Stub.get(),call))
00247 {
00248
00249
00250 result=typename detail::TypeWrap<R>::type();
00251 }
00252 return result;
00253 }
00254
00255 public:
00256
00260 static void set_connection(std::auto_ptr<ConnectionWrapper> wrappedConnection)
00261 {
00262 WrappedConnection=wrappedConnection;
00263
00264
00265 if (SingletonObject.get() != NULL)
00266 SingletonObject.reset();
00267 }
00268
00270 static ConnectionWrapper* get_connection_wrapper(void)
00271 { return WrappedConnection.get(); }
00272
00274 static void ensure_singleton_there(void)
00275 {
00276 if (SingletonObject.get() == NULL)
00277 init();
00278 }
00279
00281
00282 #define _GEN_PLACEHOLDER(z,n,d) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1))
00283 #define _GEN_EXEC(z,n,d) \
00284 template< typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
00285 static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > exec \
00286 ( \
00287 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
00288 ) \
00289 { \
00290 boost::function<R(Client*)>(*p)(R(Client::*)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
00291 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg)) \
00292 = &T2nSingletonWrapper::template prep<R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg) >; \
00293 return boost::bind \
00294 ( \
00295 T2nSingletonWrapper::template real_exec<R>, \
00296 boost::bind( p, f BOOST_PP_COMMA_IF(n) \
00297 BOOST_PP_ENUM(n, _GEN_PLACEHOLDER, ~ ) ) \
00298 ); \
00299 } // eo exec
00300
00301 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
00302
00303 #undef _GEN_EXEC
00304 #undef _GEN_PLACEHOLDER
00306
00307 };
00308
00310
00311 #define _GEN_EXEC(z,n,d) \
00312 template< class Client, typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
00313 static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > t2n_exec \
00314 ( \
00315 R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
00316 ) \
00317 { \
00318 return T2nSingletonWrapper<Client>::exec(f); \
00319 } // eo exec
00320
00321 BOOST_PP_REPEAT( BOOST_PP_ADD(T2N_SINGLETON_WRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
00322
00323 #undef _GEN_EXEC
00324 #undef _GEN_PLACEHOLDER
00326
00327 }
00328 #endif