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