Sirikata
|
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_