X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FDispatch.cc;fp=src%2FMoof%2FDispatch.cc;h=17f8f172803901513733b4fc8905b9717848ab1e;hp=0000000000000000000000000000000000000000;hb=e495074443d9fd7bc16137084cf9de3d031b75c4;hpb=c9e20ac06383b20ceb5404c9237e319c2e90d157 diff --git a/src/Moof/Dispatch.cc b/src/Moof/Dispatch.cc new file mode 100644 index 0000000..17f8f17 --- /dev/null +++ b/src/Moof/Dispatch.cc @@ -0,0 +1,165 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include + +#include "Dispatch.hh" + + +namespace Mf { + + +class Dispatch::Impl +{ +public: + + Impl() : + mId(0) {} + + Dispatch::Handler getNewHandler() + { + ++mId; + //return Dispatch::Handler(this, mId); + Dispatch::Handler handler(this, mId); + return handler; + } + + typedef std::pair Callback; + typedef std::multimap CallbackLookup; + typedef CallbackLookup::iterator CallbackIter; + + typedef std::multimap HandlerLookup; + typedef HandlerLookup::iterator HandlerIter; + + + inline Handler addHandler(const std::string& event, + const Function& callback, Handler handler) + { + mCallbacks.insert(std::make_pair(event, + std::make_pair(handler.getId(), callback))); + mHandlers.insert(std::make_pair(handler.getId(), event)); + + return handler; + } + + inline void removeHandler(unsigned id) + { + std::pair matching(mHandlers.equal_range(id)); + + for (HandlerIter it = matching.first; it != matching.second; ++it) + { + CallbackIter first = mCallbacks.find((*it).second); + CallbackIter last = mCallbacks.end(); + + for (CallbackIter jt = first; jt != last; ++jt) + { + if ((*jt).second.first == id) + { + mCallbacks.erase(jt); + break; + } + } + } + + mHandlers.erase(id); + } + + void dispatch(const std::string& event, const Message* message) + { + std::pair + callbacks(mCallbacks.equal_range(event)); + + for (CallbackIter it = callbacks.first; it != callbacks.second; ++it) + { + Function callback = (*it).second.second; + callback(message); + } + } + + + unsigned mId; + + CallbackLookup mCallbacks; + HandlerLookup mHandlers; +}; + + +Dispatch::Handler::~Handler() +{ + if (mId) + { + mDispatch->removeHandler(mId); + } +} + + +Dispatch::Dispatch() : + mImpl(new Dispatch::Impl) {} + +Dispatch::~Dispatch() {} + + +Dispatch& Dispatch::getInstance() +{ + static Dispatch dispatch; + return dispatch; +} + + +Dispatch::Handler Dispatch::addHandler(const std::string& event, + const Function& callback) +{ + return addHandler(event, callback, mImpl->getNewHandler()); +} + +Dispatch::Handler Dispatch::addHandler(const std::string& event, + const Function& callback, Handler handler) +{ + // pass through + return mImpl->addHandler(event, callback, handler); +} + + +void Dispatch::removeHandler(unsigned id) +{ + // pass through + return mImpl->removeHandler(id); +} + + +void Dispatch::dispatch(const std::string& event, const Message* message) +{ + // pass through + mImpl->dispatch(event, message); +} + + +} // namespace Mf + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ +