[Xorp-hackers] [PATCH] XrlCmdEntry provides method to convert synchronous function into asynchronous one. XrlCmdMap made full asynchronous, but extended to accept synchronous command implementations, from which it build asynchronous ones. Conditional declarations are now only used by tgt-gen.

ss at comp.lancs.ac.uk ss at comp.lancs.ac.uk
Mon Apr 11 03:25:21 PDT 2011


From: Steven Simpson <ss at comp.lancs.ac.uk>

XrlCmdMap::add_handler renamed to *_internal; also where inherited by
XrlDispatcher and XrlRouter.  New add_handler methods added to allow
acceptance of both sync and async command implementations.

Async conditionals dropped from FinderMessengerBase and XrlDispatcher,
as they now use the new unconditionally asynchronous XrlCmdMap
interface.

Signed-off-by: Steven Simpson <ss at comp.lancs.ac.uk>
---
 xorp/libxipc/finder_messenger.cc |    6 ---
 xorp/libxipc/xrl_cmd_map.cc      |   11 ++++-
 xorp/libxipc/xrl_cmd_map.hh      |   85 +++++++++++++++++++++++++++++++++-----
 xorp/libxipc/xrl_dispatcher.cc   |   12 -----
 xorp/libxipc/xrl_router.cc       |    5 +-
 xorp/libxipc/xrl_router.hh       |    3 +-
 6 files changed, 89 insertions(+), 33 deletions(-)

diff --git a/xorp/libxipc/finder_messenger.cc b/xorp/libxipc/finder_messenger.cc
index 5ee4353..63db5db 100644
--- a/xorp/libxipc/finder_messenger.cc
+++ b/xorp/libxipc/finder_messenger.cc
@@ -97,14 +97,8 @@ FinderMessengerBase::dispatch_xrl(uint32_t seqno, const Xrl& xrl)
     if (manager())
 	manager()->messenger_active_event(this);
     
-#ifdef XORP_ENABLE_ASYNC_SERVER
     ce->dispatch(xrl.args(),
 		 callback(this, &FinderMessengerBase::dispatch_xrl_cb, seqno));
-#else
-    XrlArgs reply_args;
-    XrlCmdError e = ce->dispatch(xrl.args(), &reply_args);
-    dispatch_xrl_cb(e, &reply_args, seqno);
-#endif
 
     // Announce we've dispatched xrl
     if (manager())
diff --git a/xorp/libxipc/xrl_cmd_map.cc b/xorp/libxipc/xrl_cmd_map.cc
index 487f68e..38bb639 100644
--- a/xorp/libxipc/xrl_cmd_map.cc
+++ b/xorp/libxipc/xrl_cmd_map.cc
@@ -28,6 +28,14 @@
 
 #include "xrl_cmd_map.hh"
 
+void
+XrlCmdEntry::invoke_sync(const XrlArgs& in, XrlRespCallback out,
+			 XrlRecvSyncCallback impl)
+{
+    XrlArgs out_args;
+    XrlCmdError e = impl->dispatch(in, &out_args);
+    out->dispatch(e, &out_args);
+}
 
 bool
 XrlCmdMap::add_handler(const XrlCmdEntry& cmd)
@@ -42,7 +50,8 @@ XrlCmdMap::add_handler(const XrlCmdEntry& cmd)
 }
 
 bool
-XrlCmdMap::add_handler(const string& cmd, const XrlRecvCallback& rcb)
+XrlCmdMap::add_handler_internal(const string& cmd,
+				const XrlRecvAsyncCallback& rcb)
 {
     return add_handler(XrlCmdEntry(cmd, rcb));
 }
diff --git a/xorp/libxipc/xrl_cmd_map.hh b/xorp/libxipc/xrl_cmd_map.hh
index 33b8d7d..8566cff 100644
--- a/xorp/libxipc/xrl_cmd_map.hh
+++ b/xorp/libxipc/xrl_cmd_map.hh
@@ -32,54 +32,108 @@
 #include "xrl.hh"
 #include "xrl_error.hh"
 
+
+
+
+
+// This the the original, synchronous, command callback.
+// Out-arguments and error code must be set by the time the function
+// returns.
+typedef
+XorpCallback2<const XrlCmdError, const XrlArgs&, XrlArgs*>::RefPtr
+XrlRecvSyncCallback;
+
+// This is the type of callback that a command implementation must
+// call if it wants to operate asynchronously.
+typedef
+XorpCallback2<void, const XrlCmdError &, const XrlArgs *>::RefPtr
+XrlRespCallback;
+
+// This is the new, asynchronous, command callback.  No errors are
+// returned, nor out-arguments passed.  Instead, the XrlRespCallback
+// is invoked with the results.
+typedef
+XorpCallback2<void, const XrlArgs&, XrlRespCallback>::RefPtr
+XrlRecvAsyncCallback;
+
+
+
+// We define some types depending on whether asynchronous
+// implementations are allowed.
 #ifdef XORP_ENABLE_ASYNC_SERVER
+
+// Asynchronous implementations do not return anything.
 typedef void XrlCmdRT;
 
+// To report an error, invoke the callback, and stop.
 #define XRL_CMD_RETURN_ERROR(OUT, ERR)	\
     do {				\
 	(OUT)->dispatch((ERR), NULL);	\
 	return;				\
     } while (0)
 
-typedef
-XorpCallback2<void, const XrlCmdError &, const XrlArgs *>::RefPtr
-XrlRespCallback;
-
+// Responses are expressed through a callback.
 typedef XrlRespCallback XrlCmdOT;
 
+// The normal command implementation type is the asynchronous version.
+typedef XrlRecvAsyncCallback XrlRecvCallback;
+
+
 #else
 
+
+// Synchronous implementations return the error code.
 typedef const XrlCmdError XrlCmdRT;
 
+// To report an error, return it.
 #define XRL_CMD_RETURN_ERROR(OUT, ERR)	\
     do {				\
 	return (ERR);			\
     } while (0)
 
+// Placeholders for out-arguments are supplied to the command
+// implementation.
 typedef XrlArgs* XrlCmdOT;
 
+// The normal command implementation type is the synchronous version.
+typedef XrlRecvSyncCallback XrlRecvCallback;
+
 #endif
 
-typedef
-XorpCallback2<XrlCmdRT, const XrlArgs&, XrlCmdOT>::RefPtr XrlRecvCallback;
+
+
 
 class XrlCmdEntry {
+    // An asynchronous command implementation that calls a synchronous
+    // one
+    static void invoke_sync(const XrlArgs& in, XrlRespCallback out,
+			    XrlRecvSyncCallback impl);
+
 public:
-    XrlCmdEntry(const string& s, XrlRecvCallback cb) :
+    // Make an asynchronous command implementation out of a
+    // synchronous one.
+    static XrlRecvAsyncCallback make_async_cb(const XrlRecvSyncCallback& cb) {
+	return callback(&XrlCmdEntry::invoke_sync, cb);
+    }
+
+    XrlCmdEntry(const string& s, XrlRecvAsyncCallback cb) :
 	    _name(s), _cb(cb) {}
+    XrlCmdEntry(const string& s, XrlRecvSyncCallback cb) :
+	    _name(s), _cb(make_async_cb(cb)) {}
+
 #ifdef XORP_USE_USTL
     XrlCmdEntry() { }
 #endif
 
     const string& name() const { return _name; }
 
-    XrlCmdRT dispatch(const XrlArgs& inputs, XrlCmdOT outputs) const {
+    void dispatch(const XrlArgs& inputs, XrlRespCallback outputs) const {
 	return _cb->dispatch(inputs, outputs);
     }
 
 protected:
-    string		_name;
-    XrlRecvCallback	_cb;
+    string			_name;
+    XrlRecvAsyncCallback	_cb;
 };
 
 class XrlCmdMap :
@@ -93,7 +147,16 @@ public:
 
     const string& name() const { return _name; }
 
-    virtual bool add_handler(const string& cmd, const XrlRecvCallback& rcb);
+    virtual bool add_handler_internal(const string& cmd,
+				      const XrlRecvAsyncCallback& rcb);
+
+    bool add_handler(const string& cmd, const XrlRecvAsyncCallback& rcb) {
+	return add_handler_internal(cmd, rcb);
+    }
+
+    bool add_handler(const string& cmd, const XrlRecvSyncCallback& rcb) {
+	return add_handler_internal(cmd, XrlCmdEntry::make_async_cb(rcb));
+    }
 
     virtual bool remove_handler (const string& name);
 
diff --git a/xorp/libxipc/xrl_dispatcher.cc b/xorp/libxipc/xrl_dispatcher.cc
index c9a556e..37a8c01 100644
--- a/xorp/libxipc/xrl_dispatcher.cc
+++ b/xorp/libxipc/xrl_dispatcher.cc
@@ -64,14 +64,8 @@ XrlDispatcher::dispatch_xrl(const string&  method_name,
     }
 
     trace_xrl_dispatch("dispatch_xrl (valid) ", method_name);
-#ifdef XORP_ENABLE_ASYNC_SERVER
     XrlRespCallback resp = callback(this, &XrlDispatcher::dispatch_cb, outputs);
     return c->dispatch(inputs, resp);
-#else
-    XrlArgs resp;
-    XrlCmdError e = c->dispatch(inputs, &resp);
-    outputs->dispatch(e, &resp);
-#endif
 }
 
 XrlDispatcher::XI*
@@ -88,14 +82,8 @@ void
 XrlDispatcher::dispatch_xrl_fast(const XI& xi,
 				 XrlDispatcherCallback outputs) const
 {
-#ifdef XORP_ENABLE_ASYNC_SERVER
     XrlRespCallback resp = callback(this, &XrlDispatcher::dispatch_cb, outputs);
     return xi._cmd->dispatch(xi._xrl.args(), resp);
-#else
-    XrlArgs resp;
-    XrlCmdError e = xi._cmd->dispatch(xi._xrl.args(), &resp);
-    return outputs->dispatch(e, &resp);
-#endif
 }
 
 void
diff --git a/xorp/libxipc/xrl_router.cc b/xorp/libxipc/xrl_router.cc
index ed66b66..2975e3e 100644
--- a/xorp/libxipc/xrl_router.cc
+++ b/xorp/libxipc/xrl_router.cc
@@ -372,14 +372,15 @@ XrlRouter::finalize()
 }
 
 bool
-XrlRouter::add_handler(const string& cmd, const XrlRecvCallback& rcb)
+XrlRouter::add_handler_internal(const string& cmd,
+				const XrlRecvAsyncCallback& rcb)
 {
     if (finalized()) {
 	XLOG_ERROR("Attempting to add handler after XrlRouter finalized.  Handler = \"%s\"", cmd.c_str());
 	return false;
     }
 
-    return XrlCmdMap::add_handler(cmd, rcb);
+    return XrlCmdMap::add_handler_internal(cmd, rcb);
 }
 
 void
diff --git a/xorp/libxipc/xrl_router.hh b/xorp/libxipc/xrl_router.hh
index 5de0194..0679bf1 100644
--- a/xorp/libxipc/xrl_router.hh
+++ b/xorp/libxipc/xrl_router.hh
@@ -130,7 +130,8 @@ public:
      * @param rcb callback to be dispatched when XRL method is received for
      * invocation.
      */
-    bool add_handler(const string& cmd, const XrlRecvCallback& rcb);
+    bool add_handler_internal(const string& cmd,
+			      const XrlRecvAsyncCallback& rcb);
 
     /**
      * @return EventLoop used by XrlRouter instance.
-- 
1.7.0.4



More information about the Xorp-hackers mailing list