Sirikata
libcore/include/sirikata/core/xdp/DelegatePort.hpp
Go to the documentation of this file.
00001 // Copyright (c) 2011 Sirikata Authors. All rights reserved.
00002 // Use of this source code is governed by a BSD-style license that can
00003 // be found in the LICENSE file.
00004 
00005 #ifndef _SIRIKATA_LIBCORE_XDP_DELEGATE_PORT_HPP_
00006 #define _SIRIKATA_LIBCORE_XDP_DELEGATE_PORT_HPP_
00007 
00008 #include <sirikata/core/xdp/Defs.hpp>
00009 
00010 namespace Sirikata {
00011 namespace XDP {
00012 
00013 class DelegateService;
00014 
00022 template<typename EndpointType, typename DelegateServiceType, typename PortType = Sirikata::XDP::Port<EndpointType> >
00023 class DelegatePort : public PortType {
00024 public:
00025     typedef EndpointType Endpoint;
00026     typedef PortType Port;
00027     typedef DelegateServiceType DelegateService;
00028     typedef typename DelegateServiceType::MessageHandler MessageHandler;
00029 
00030     typedef std::tr1::function<bool(const Endpoint&, MemoryReference payload)> SendFunction;
00031 
00038     DelegatePort(DelegateService* parent, const Endpoint& ep, SendFunction send_func)
00039         : mParent(parent),
00040         mEndpoint(ep),
00041         mSendFunc(send_func),
00042         mFromHandlers(),
00043         mInvalidated(false)
00044         {
00045         }
00046 
00047     virtual ~DelegatePort() {
00048         // Get it out of the parent map to ensure we won't get any more messages
00049         if (!mInvalidated)
00050             mParent->deallocatePort(this);
00051     }
00052 
00053 
00054     // Port Interface
00055     virtual const Endpoint& endpoint() const { return mEndpoint; }
00056     virtual bool send(const Endpoint& to, MemoryReference payload) {
00057         if (mInvalidated) return false;
00058         return mSendFunc(to, payload);
00059     }
00060     virtual void receiveFrom(const Endpoint& from, const MessageHandler& cb) {
00061         mFromHandlers[from] = cb;
00062     }
00063 
00067     bool deliver(const Endpoint& src, const Endpoint& dst, MemoryReference data) const {
00068         if (mInvalidated) return false;
00069 
00070         // See Port documentation for details on this ordering.
00071         if (tryDeliver(src, src, dst, data)) return true;
00072         if (tryDeliver(Endpoint(src.space(), Endpoint::Identifier::any(), src.port()), src, dst, data)) return true;
00073         if (tryDeliver(Endpoint(SpaceID::any(), Endpoint::Identifier::any(), src.port()), src, dst, data)) return true;
00074         if (tryDeliver(Endpoint(src.space(), src.id(), PortID::any()), src, dst, data)) return true;
00075         if (tryDeliver(Endpoint(src.space(), Endpoint::Identifier::any(), PortID::any()), src, dst, data)) return true;
00076         if (tryDeliver(Endpoint(SpaceID::any(), Endpoint::Identifier::any(), PortID::any()), src, dst, data)) return true;
00077 
00078         return false;
00079     }
00080 
00086     void invalidate() {
00087         // Mark and remove from parent
00088         mInvalidated = true;
00089         mParent->deallocatePort(this);
00090     }
00091 
00092 private:
00093     // Worker method for deliver, tries to deliver to the handler for this exact
00094     // endpoint.
00095     // \deprecated Prefer the version using both Endpoints
00096 
00097     bool tryDeliver(const Endpoint& src_match_ep, const Endpoint& src_real_ep, const Endpoint& dst, MemoryReference data) const {
00098         typename ReceiveFromHandlers::const_iterator rit = mFromHandlers.find(src_match_ep);
00099 
00100         if (rit == mFromHandlers.end())
00101             return false;
00102 
00103         const MessageHandler& handler = rit->second;
00104 
00105         handler(src_real_ep, dst, data);
00106 
00107         return true;
00108     }
00109 
00110 
00111     typedef std::tr1::unordered_map<Endpoint, MessageHandler, typename Endpoint::Hasher> ReceiveFromHandlers;
00112 
00113     DelegateService* mParent;
00114     Endpoint mEndpoint;
00115     SendFunction mSendFunc;
00116     ReceiveFromHandlers mFromHandlers;
00117     bool mInvalidated;
00118 }; // class DelegatePort
00119 
00120 } // namespace XDP
00121 } // namespace Sirikata
00122 
00123 #endif //_SIRIKATA_LIBCORE_XDP_DELEGATE_PORT_HPP_