InspIRCd  3.0
event.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  * Copyright (C) 2018-2021 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 #include "base.h"
24 
25 namespace Events
26 {
27  class ModuleEventListener;
28  class ModuleEventProvider;
29 }
30 
38 {
39  public:
40  struct Comp
41  {
42  bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const;
43  };
44 
45  struct ElementComp
46  {
47  bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const;
48  };
49 
51 
56  ModuleEventProvider(Module* mod, const std::string& eventid)
57  : ServiceProvider(mod, eventid, SERVICE_DATA)
58  , prov(mod, eventid)
59  {
60  prov.SetCaptureHook(this);
61  }
62 
64  const Module* GetModule() const { return prov.creator; }
65 
69  const SubscriberList& GetSubscribers() const { return prov->subscribers; }
70 
74  void Subscribe(ModuleEventListener* subscriber)
75  {
76  subscribers.insert(subscriber);
77  OnSubscribe(subscriber);
78  }
79 
83  void Unsubscribe(ModuleEventListener* subscriber)
84  {
85  subscribers.erase(subscriber);
86  OnUnsubscribe(subscriber);
87  }
88 
89  private:
90  void OnCapture() CXX11_OVERRIDE
91  {
92  // If someone else holds the list from now on, clear mine. See below for more info.
93  if (*prov != this)
94  subscribers.clear();
95  }
96 
100  virtual void OnSubscribe(ModuleEventListener* subscriber) { }
101 
105  virtual void OnUnsubscribe(ModuleEventListener* subscriber) { }
106 
113 
117  SubscriberList subscribers;
118 };
119 
124 {
128 
129  const unsigned int eventpriority;
130 
133  void OnCapture() CXX11_OVERRIDE
134  {
135  prov->Subscribe(this);
136  }
137 
138  public:
139  static const unsigned int DefaultPriority = 100;
140 
146  ModuleEventListener(Module* mod, const std::string& eventid, unsigned int eventprio = DefaultPriority)
147  : prov(mod, eventid)
148  , eventpriority(eventprio)
149  {
150  prov.SetCaptureHook(this);
151  // If the dynamic_reference resolved at construction our capture handler wasn't called
152  if (prov)
153  ModuleEventListener::OnCapture();
154  }
155 
157  {
158  if (prov)
159  prov->Unsubscribe(this);
160  }
161 
163  const Module* GetModule() const { return prov.creator; }
164 
166  unsigned int GetPriority() const { return eventpriority; }
167 };
168 
169 inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
170 {
171  return (lhs->GetPriority() < rhs->GetPriority());
172 }
173 
174 inline bool Events::ModuleEventProvider::ElementComp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
175 {
176  if (lhs->GetPriority() < rhs->GetPriority())
177  return true;
178  if (lhs->GetPriority() > rhs->GetPriority())
179  return false;
180  return std::less<ModuleEventListener*>()(lhs, rhs);
181 }
182 
188 #define FOREACH_MOD_CUSTOM(prov, listenerclass, func, params) do { \
189  if (!(prov).GetModule() || !(prov).GetModule()->dying) \
190  { \
191  const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \
192  for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \
193  { \
194  listenerclass* _t = static_cast<listenerclass*>(*_i); \
195  const Module* _m = _t->GetModule(); \
196  if (_m && !_m->dying) \
197  _t->func params ; \
198  } \
199  } \
200 } while (0);
201 
209 #define FIRST_MOD_RESULT_CUSTOM(prov, listenerclass, func, result, params) do { \
210  result = MOD_RES_PASSTHRU; \
211  if (!(prov).GetModule() || !(prov).GetModule()->dying) \
212  { \
213  const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \
214  for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \
215  { \
216  listenerclass* _t = static_cast<listenerclass*>(*_i); \
217  const Module* _m = _t->GetModule(); \
218  if (!_m || _m->dying) \
219  continue; \
220  result = _t->func params ; \
221  if (result != MOD_RES_PASSTHRU) \
222  break; \
223  } \
224  } \
225 } while (0);
Definition: event.h:124
ModuleEventListener(Module *mod, const std::string &eventid, unsigned int eventprio=DefaultPriority)
Definition: event.h:146
const Module * GetModule() const
Definition: event.h:163
unsigned int GetPriority() const
Definition: event.h:166
Definition: event.h:38
ModuleEventProvider(Module *mod, const std::string &eventid)
Definition: event.h:56
void Subscribe(ModuleEventListener *subscriber)
Definition: event.h:74
const SubscriberList & GetSubscribers() const
Definition: event.h:69
const Module * GetModule() const
Definition: event.h:64
void Unsubscribe(ModuleEventListener *subscriber)
Definition: event.h:83
Definition: modules.h:318
Definition: base.h:249
void SetCaptureHook(CaptureHook *h)
Definition: dynref.h:52
Definition: dynref.h:96
Definition: event.h:41