/*] Copyright (c) 2009-2010, Charles McGarvey [************************** **] All rights reserved. * * vi:ts=4 sw=4 tw=75 * * Distributable under the terms and conditions of the 2-clause BSD license; * see the file COPYING for a complete text of the license. * **************************************************************************/ #include #include "Dispatch.hh" namespace Mf { class Dispatch::Impl { public: Impl(Dispatch* dispatch) : mDispatch(dispatch), mId(0) {} Dispatch::Handle getNewHandle() { ++mId; Dispatch::Handle handle(mDispatch->mImpl, mId); return handle; } typedef std::pair Callback; typedef std::multimap CallbackLookup; typedef CallbackLookup::iterator CallbackIt; typedef std::multimap HandleLookup; typedef HandleLookup::iterator HandleIt; inline Handle addTarget(const std::string& event, const Function& callback, Handle handle) { mCallbacks.insert(std::make_pair(event, std::make_pair(handle.getId(), callback))); mHandles.insert(std::make_pair(handle.getId(), event)); return handle; } inline void removeTarget(unsigned id) { std::pair matching(mHandles.equal_range(id)); for (HandleIt it = matching.first; it != matching.second; ++it) { CallbackIt first = mCallbacks.find((*it).second); CallbackIt last = mCallbacks.end(); for (CallbackIt jt = first; jt != last; ++jt) { if ((*jt).second.first == id) { mCallbacks.erase(jt); break; } } } mHandles.erase(id); } void dispatch(const std::string& event) { std::pair callbacks(mCallbacks.equal_range(event)); for (CallbackIt it = callbacks.first; it != callbacks.second; ++it) { Function callback = (*it).second.second; callback(); } } Dispatch* mDispatch; unsigned mId; CallbackLookup mCallbacks; HandleLookup mHandles; }; void Dispatch::Handle::clear() { boost::shared_ptr dispatch; if (mId && (dispatch = mDispatch.lock())) { dispatch->removeTarget(mId); mId = 0; } } Dispatch::Dispatch() : mImpl(new Dispatch::Impl(this)) {} Dispatch::Handle Dispatch::addTarget(const std::string& event, const Function& callback) { return addTarget(event, callback, mImpl->getNewHandle()); } Dispatch::Handle Dispatch::addTarget(const std::string& event, const Function& callback, Handle handle) { // pass through return mImpl->addTarget(event, callback, handle); } void Dispatch::removeTarget(unsigned id) { // pass through return mImpl->removeTarget(id); } void Dispatch::dispatch(const std::string& event) { // pass through mImpl->dispatch(event); } Dispatch& Dispatch::global() { static Dispatch dispatch; return dispatch; } } // namespace Mf