client_wrapper.hxx

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2008 by Gerd v. Egidy and Reinhard Pfau                 *
00003  *   gve@intra2net.com                                                     *
00004  *                                                                         *
00005  *   This library is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License version   *
00007  *   2.1 as published by the Free Software Foundation.                     *
00008  *                                                                         *
00009  *   This library is distributed in the hope that it will be useful,       *
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00012  *   GNU Lesser General Public License for more details.                   *
00013  *                                                                         *
00014  *   You should have received a copy of the GNU Lesser General Public      *
00015  *   License along with this program; if not, write to the                 *
00016  *   Free Software Foundation, Inc.,                                       *
00017  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
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 // contains the internal stuff needed for T2nWrapper
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 } // eo namespace detail
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         // create a prep-method for each possible number of parameters
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             // bind our Client-object and the local result
00239             detail::Call<R> call( boost::bind( f, SingletonObject->Stub.get()), result );
00240 
00241             // let the wrapper-handler call the fully-bound function
00242             if (!WrappedConnection->handle(SingletonObject->Stub.get(),call))
00243             {
00244                 // create an result with default-constructor if the handler could not
00245                 // successfully do a call but no exception occured
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             // reset the singleton to NULL because the singleton must be constructed with current WrappedConnection
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         // create an exec-method for each possible number of parameters
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 // create an t2n_exec-method for each possible number of parameters
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

Generated on Fri Sep 26 15:36:59 2008 for libt2n by  doxygen 1.5.6