InspIRCd  3.0
event.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  * Copyright (C) 2018-2020 Sadie Powell <[email protected]>
5  * Copyright (C) 2015, 2018 Attila Molnar <[email protected]>
6  *
7  * This file is part of InspIRCd. InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 #pragma once
22 
23 namespace Events
24 {
25  class ModuleEventListener;
26  class ModuleEventProvider;
27 }
28 
36 {
37  public:
38  struct Comp
39  {
40  bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const;
41  };
42 
43  struct ElementComp
44  {
45  bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const;
46  };
47 
49 
54  ModuleEventProvider(Module* mod, const std::string& eventid)
55  : ServiceProvider(mod, eventid, SERVICE_DATA)
56  , prov(mod, eventid)
57  {
58  prov.SetCaptureHook(this);
59  }
60 
62  const Module* GetModule() const { return prov.creator; }
63 
67  const SubscriberList& GetSubscribers() const { return prov->subscribers; }
68 
72  void Subscribe(ModuleEventListener* subscriber)
73  {
74  subscribers.insert(subscriber);
75  OnSubscribe(subscriber);
76  }
77 
81  void Unsubscribe(ModuleEventListener* subscriber)
82  {
83  subscribers.erase(subscriber);
84  OnUnsubscribe(subscriber);
85  }
86 
87  private:
88  void OnCapture() CXX11_OVERRIDE
89  {
90  // If someone else holds the list from now on, clear mine. See below for more info.
91  if (*prov != this)
92  subscribers.clear();
93  }
94 
98  virtual void OnSubscribe(ModuleEventListener* subscriber) { }
99 
103  virtual void OnUnsubscribe(ModuleEventListener* subscriber) { }
104 
111 
115  SubscriberList subscribers;
116 };
117 
122 {
126 
127  const unsigned int eventpriority;
128 
131  void OnCapture() CXX11_OVERRIDE
132  {
133  prov->Subscribe(this);
134  }
135 
136  public:
137  static const unsigned int DefaultPriority = 100;
138 
144  ModuleEventListener(Module* mod, const std::string& eventid, unsigned int eventprio = DefaultPriority)
145  : prov(mod, eventid)
146  , eventpriority(eventprio)
147  {
148  prov.SetCaptureHook(this);
149  // If the dynamic_reference resolved at construction our capture handler wasn't called
150  if (prov)
151  ModuleEventListener::OnCapture();
152  }
153 
155  {
156  if (prov)
157  prov->Unsubscribe(this);
158  }
159 
161  const Module* GetModule() const { return prov.creator; }
162 
164  unsigned int GetPriority() const { return eventpriority; }
165 };
166 
167 inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
168 {
169  return (lhs->GetPriority() < rhs->GetPriority());
170 }
171 
172 inline bool Events::ModuleEventProvider::ElementComp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
173 {
174  if (lhs->GetPriority() < rhs->GetPriority())
175  return true;
176  if (lhs->GetPriority() > rhs->GetPriority())
177  return false;
178  return std::less<ModuleEventListener*>()(lhs, rhs);
179 }
180 
186 #define FOREACH_MOD_CUSTOM(prov, listenerclass, func, params) do { \
187  if (!(prov).GetModule() || !(prov).GetModule()->dying) \
188  { \
189  const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \
190  for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \
191  { \
192  listenerclass* _t = static_cast<listenerclass*>(*_i); \
193  const Module* _m = _t->GetModule(); \
194  if (_m && !_m->dying) \
195  _t->func params ; \
196  } \
197  } \
198 } while (0);
199 
207 #define FIRST_MOD_RESULT_CUSTOM(prov, listenerclass, func, result, params) do { \
208  result = MOD_RES_PASSTHRU; \
209  if (!(prov).GetModule() || !(prov).GetModule()->dying) \
210  { \
211  const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \
212  for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \
213  { \
214  listenerclass* _t = static_cast<listenerclass*>(*_i); \
215  const Module* _m = _t->GetModule(); \
216  if (!_m || _m->dying) \
217  continue; \
218  result = _t->func params ; \
219  if (result != MOD_RES_PASSTHRU) \
220  break; \
221  } \
222  } \
223 } while (0);
dynamic_reference_base::SetCaptureHook
void SetCaptureHook(CaptureHook *h)
Definition: dynref.h:52
ServiceProvider
Definition: base.h:250
Events::ModuleEventListener::ModuleEventListener
ModuleEventListener(Module *mod, const std::string &eventid, unsigned int eventprio=DefaultPriority)
Definition: event.h:144
Events::ModuleEventListener::GetPriority
unsigned int GetPriority() const
Definition: event.h:164
dynamic_reference_nocheck
Definition: dynref.h:95
Events::ModuleEventProvider::Unsubscribe
void Unsubscribe(ModuleEventListener *subscriber)
Definition: event.h:81
Events::ModuleEventProvider::GetModule
const Module * GetModule() const
Definition: event.h:62
dynamic_reference_base::CaptureHook
Definition: dynref.h:28
Events::ModuleEventProvider::ElementComp
Definition: event.h:43
Events::ModuleEventProvider::Comp
Definition: event.h:38
insp::flat_multiset< ModuleEventListener *, Comp, ElementComp >
Events::ModuleEventProvider
Definition: event.h:35
Events::ModuleEventListener
Definition: event.h:121
Module
Definition: modules.h:316
Events::ModuleEventProvider::GetSubscribers
const SubscriberList & GetSubscribers() const
Definition: event.h:67
Events::ModuleEventListener::GetModule
const Module * GetModule() const
Definition: event.h:161
Events::ModuleEventProvider::Subscribe
void Subscribe(ModuleEventListener *subscriber)
Definition: event.h:72
Events::ModuleEventProvider::ModuleEventProvider
ModuleEventProvider(Module *mod, const std::string &eventid)
Definition: event.h:54