X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=include%2Fevent.h;h=baa24d7d08798b9f5c9a370dac3bae2af1f64510;hb=2ba32afa9a9aca7c82966b66bda16c3c3dbfbba5;hp=73a45a5419a7396950851e210078e7cdebfb6aa3;hpb=c6e40d36b42a7ebf832c3a57d2816a47ee9c9a76;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/include/event.h b/include/event.h index 73a45a541..baa24d7d0 100644 --- a/include/event.h +++ b/include/event.h @@ -1,7 +1,8 @@ /* * InspIRCd -- Internet Relay Chat Daemon * - * Copyright (C) 2015 Attila Molnar + * Copyright (C) 2018-2020 Sadie Powell + * Copyright (C) 2015, 2018 Attila Molnar * * This file is part of InspIRCd. InspIRCd is free software: you can * redistribute it and/or modify it under the terms of the GNU General Public @@ -19,6 +20,8 @@ #pragma once +#include "base.h" + namespace Events { class ModuleEventListener; @@ -36,10 +39,15 @@ class Events::ModuleEventProvider : public ServiceProvider, private dynamic_refe public: struct Comp { - bool operator()(ModuleEventListener* one, ModuleEventListener* two) const; + bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const; }; - typedef insp::flat_multiset SubscriberList; + struct ElementComp + { + bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const; + }; + + typedef insp::flat_multiset SubscriberList; /** Constructor * @param mod Module providing the event(s) @@ -52,12 +60,31 @@ class Events::ModuleEventProvider : public ServiceProvider, private dynamic_refe prov.SetCaptureHook(this); } + /** Retrieves the module which created this listener. */ + const Module* GetModule() const { return prov.creator; } + /** Get list of objects subscribed to this event * @return List of subscribed objects */ const SubscriberList& GetSubscribers() const { return prov->subscribers; } - friend class ModuleEventListener; + /** Subscribes a listener to this event. + * @param subscriber The listener to subscribe. + */ + void Subscribe(ModuleEventListener* subscriber) + { + subscribers.insert(subscriber); + OnSubscribe(subscriber); + } + + /** Unsubscribes a listener from this event. + * @param subscriber The listener to unsubscribe. + */ + void Unsubscribe(ModuleEventListener* subscriber) + { + subscribers.erase(subscriber); + OnUnsubscribe(subscriber); + } private: void OnCapture() CXX11_OVERRIDE @@ -67,6 +94,16 @@ class Events::ModuleEventProvider : public ServiceProvider, private dynamic_refe subscribers.clear(); } + /** Called when a listener subscribes to this event. + * @param subscriber The listener which subscribed. + */ + virtual void OnSubscribe(ModuleEventListener* subscriber) { } + + /** Called when a listener unsubscribes from this event. + * @param subscriber The listener which unsubscribed. + */ + virtual void OnUnsubscribe(ModuleEventListener* subscriber) { } + /** Reference to the active provider for this event. In case multiple event providers * exist for the same event, only one of them contains the list of subscribers. * To handle the case when we are not the ones with the list, we get it from the provider @@ -95,7 +132,7 @@ class Events::ModuleEventListener : private dynamic_reference_base::CaptureHook */ void OnCapture() CXX11_OVERRIDE { - prov->subscribers.insert(this); + prov->Subscribe(this); } public: @@ -104,6 +141,7 @@ class Events::ModuleEventListener : private dynamic_reference_base::CaptureHook /** Constructor * @param mod Module subscribing * @param eventid Identifier of the event to subscribe to + * @param eventprio The priority to give this event listener */ ModuleEventListener(Module* mod, const std::string& eventid, unsigned int eventprio = DefaultPriority) : prov(mod, eventid) @@ -118,15 +156,28 @@ class Events::ModuleEventListener : private dynamic_reference_base::CaptureHook ~ModuleEventListener() { if (prov) - prov->subscribers.erase(this); + prov->Unsubscribe(this); } - friend struct ModuleEventProvider::Comp; + /** Retrieves the module which created this listener. */ + const Module* GetModule() const { return prov.creator; } + + /** Retrieves the priority of this event. */ + unsigned int GetPriority() const { return eventpriority; } }; -inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventListener* one, Events::ModuleEventListener* two) const +inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const +{ + return (lhs->GetPriority() < rhs->GetPriority()); +} + +inline bool Events::ModuleEventProvider::ElementComp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const { - return (one->eventpriority < two->eventpriority); + if (lhs->GetPriority() < rhs->GetPriority()) + return true; + if (lhs->GetPriority() > rhs->GetPriority()) + return false; + return std::less()(lhs, rhs); } /** @@ -135,11 +186,16 @@ inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventLis * FOREACH_MOD_CUSTOM(accountevprov, AccountEventListener, OnAccountChange, MOD_RESULT, (user, newaccount)) */ #define FOREACH_MOD_CUSTOM(prov, listenerclass, func, params) do { \ - const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \ - for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \ + if (!(prov).GetModule() || !(prov).GetModule()->dying) \ { \ - listenerclass* _t = static_cast(*_i); \ - _t->func params ; \ + const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \ + for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \ + { \ + listenerclass* _t = static_cast(*_i); \ + const Module* _m = _t->GetModule(); \ + if (_m && !_m->dying) \ + _t->func params ; \ + } \ } \ } while (0); @@ -152,12 +208,18 @@ inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventLis */ #define FIRST_MOD_RESULT_CUSTOM(prov, listenerclass, func, result, params) do { \ result = MOD_RES_PASSTHRU; \ - const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \ - for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \ + if (!(prov).GetModule() || !(prov).GetModule()->dying) \ { \ - listenerclass* _t = static_cast(*_i); \ - result = _t->func params ; \ - if (result != MOD_RES_PASSTHRU) \ - break; \ + const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \ + for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \ + { \ + listenerclass* _t = static_cast(*_i); \ + const Module* _m = _t->GetModule(); \ + if (!_m || _m->dying) \ + continue; \ + result = _t->func params ; \ + if (result != MOD_RES_PASSTHRU) \ + break; \ + } \ } \ } while (0);