libt2n: (gerd) some progress with T2nWrapper (compiles but not complete yet)
authorGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 23 Jul 2008 14:20:30 +0000 (14:20 +0000)
committerGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 23 Jul 2008 14:20:30 +0000 (14:20 +0000)
src/client_wrapper.hxx [new file with mode: 0644]

diff --git a/src/client_wrapper.hxx b/src/client_wrapper.hxx
new file mode 100644 (file)
index 0000000..08cd397
--- /dev/null
@@ -0,0 +1,212 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Gerd v. Egidy and Reinhard Pfau                 *
+ *   gve@intra2net.com                                                     *
+ *                                                                         *
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Lesser General Public License version   *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   This library is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU Lesser General Public License for more details.                   *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser General Public      *
+ *   License along with this program; if not, write to the                 *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef __LIBT2N_CLIENT_WRAPPER
+#define __LIBT2N_CLIENT_WRAPPER
+
+#include <functional>
+
+#include <boost/config.hpp>
+#include <boost/any.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/preprocessor.hpp>
+
+#include <client.hxx>
+#include <command_client.hxx>
+
+#ifndef T2NWRAPPER_MAX_ARGS
+#define T2NWRAPPER_MAX_ARGS 9
+#endif
+
+namespace libt2n
+{
+
+class ConnectionInitData
+{
+    public:
+
+        virtual std::auto_ptr<client_connection> createConnection()=0;
+
+        virtual ~ConnectionInitData()
+            { }
+};
+
+class TrivialHandler
+{
+    public:
+        static void handle( boost::function< void() > f)
+        {
+            f();
+        }
+};
+
+// contains the internal stuff needed for T2nWrapper
+namespace detail
+{
+
+    template< typename T >
+    struct TypeWrap
+    {
+        typedef T type;
+    };
+
+    template< >
+    struct TypeWrap< void >
+    {
+        typedef int type;
+    };
+
+    template< typename R >
+    struct Call
+    {
+        typedef boost::function< R() > FuncType;
+
+        FuncType function;
+        R& result;
+
+        Call( FuncType f, R& res ) : function(f), result( res ) {}
+
+        void operator()()
+        {
+            result= function();
+        }
+    };
+
+    template< >
+    struct Call<void>
+    {
+        typedef boost::function< void() > FuncType;
+        typedef TypeWrap< void >::type ResultType;
+
+        FuncType function;
+        ResultType& result;
+
+        Call( FuncType f, ResultType& res ) : function(f), result( res ) {}
+
+        void operator()()
+        {
+            function();
+            result= ResultType();
+        }
+    };
+} // eo namespace detail
+
+template<
+    class Client,
+    class Handler = TrivialHandler
+>
+class T2nWrapper
+{
+    private:
+
+        std::auto_ptr<client_connection> conndConn;
+        std::auto_ptr<Client> client;
+
+        static std::auto_ptr<T2nWrapper> singletonObject;
+        static std::auto_ptr<ConnectionInitData> initData;
+
+        // create a prep-method for each possible number of parameters
+#define _GEN_ARG(z,n,d) Arg ## n arg ##n
+#define _GEN_PREP(z,n,d) \
+        template< typename R  BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
+        static boost::function< R(Client*) > prep \
+        ( \
+            R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
+            BOOST_PP_COMMA_IF(n) \
+            BOOST_PP_ENUM( n, _GEN_ARG, ~ ) \
+        ) \
+        { \
+            return boost::bind< R > \
+                ( \
+                    f, _1  BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,arg) \
+                ); \
+        } // eo prep
+
+        BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1) , _GEN_PREP, ~ )
+
+#undef _GEN_PREP
+#undef _GEN_ARG
+
+        static void ensureSingletonThere(void)
+        {
+            if (singletonObject.get() == NULL)
+            {
+                // we need to initialize
+
+                if (initData.get() == NULL)
+                    throw std::logic_error("T2nWrapper singleton used before setting initData");
+
+                std::auto_ptr<client_connection> myConndConn=initData->createConnection();
+
+            }
+        }
+
+        template< typename R >
+        static
+        typename detail::TypeWrap<R>::type real_exec( boost::function< R(Client*) > f)
+        {
+            ensureSingletonThere();
+
+            typename detail::TypeWrap<R>::type result;
+            detail::Call<R> call( boost::bind( f, &(*(singletonObject->client))), result );
+            Handler::handle( call );
+            return result;
+        }
+
+    public:
+
+        static void setInitData(std::auto_ptr<ConnectionInitData> newInitData)
+            { initData=newInitData; }
+        static ConnectionInitData* getInitData(void)
+            { return initData.get(); }
+
+        T2nWrapper()
+        {
+            client=std::auto_ptr<Client>(new Client(*conndConn));
+        }
+
+        // create an exec-method for each possible number of parameters
+#define _GEN_PLACEHOLDER(z,n,d) BOOST_PP_CAT(_,BOOST_PP_ADD(n,1))
+#define _GEN_EXEC(z,n,d) \
+        template< typename R  BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,typename Arg) > \
+        static boost::function< R( BOOST_PP_ENUM_PARAMS(n,Arg) ) > exec \
+        ( \
+            R(Client::*f)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
+        ) \
+        { \
+            boost::function<R(Client*)>(*p)(R(Client::*)( BOOST_PP_ENUM_PARAMS(n,Arg) ) \
+                    BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg)) \
+                = &T2nWrapper::template prep<R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,Arg) >; \
+            return boost::bind \
+            ( \
+                T2nWrapper::template real_exec<R>, \
+                boost::bind( p, f BOOST_PP_COMMA_IF(n) \
+                BOOST_PP_ENUM(n, _GEN_PLACEHOLDER, ~ ) ) \
+            ); \
+        } // eo exec
+
+        BOOST_PP_REPEAT( BOOST_PP_ADD(T2NWRAPPER_MAX_ARGS,1), _GEN_EXEC, ~ )
+
+#undef _GEN_EXEC
+#undef _GEN_PLACEHOLDER
+
+};
+
+}
+#endif