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