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 
64  const SubscriberList& GetSubscribers() const { return prov->subscribers; }
65 
69  void Subscribe(ModuleEventListener* subscriber)
70  {
71  subscribers.insert(subscriber);
72  OnSubscribe(subscriber);
73  }
74 
78  void Unsubscribe(ModuleEventListener* subscriber)
79  {
80  subscribers.erase(subscriber);
81  OnUnsubscribe(subscriber);
82  }
83 
84  private:
85  void OnCapture() CXX11_OVERRIDE
86  {
87  // If someone else holds the list from now on, clear mine. See below for more info.
88  if (*prov != this)
89  subscribers.clear();
90  }
91 
95  virtual void OnSubscribe(ModuleEventListener* subscriber) { }
96 
100  virtual void OnUnsubscribe(ModuleEventListener* subscriber) { }
101 
108 
112  SubscriberList subscribers;
113 };
114 
119 {
123 
124  const unsigned int eventpriority;
125 
128  void OnCapture() CXX11_OVERRIDE
129  {
130  prov->Subscribe(this);
131  }
132 
133  public:
134  static const unsigned int DefaultPriority = 100;
135 
141  ModuleEventListener(Module* mod, const std::string& eventid, unsigned int eventprio = DefaultPriority)
142  : prov(mod, eventid)
143  , eventpriority(eventprio)
144  {
145  prov.SetCaptureHook(this);
146  // If the dynamic_reference resolved at construction our capture handler wasn't called
147  if (prov)
148  ModuleEventListener::OnCapture();
149  }
150 
152  {
153  if (prov)
154  prov->Unsubscribe(this);
155  }
156 
158  const Module* GetModule() const { return prov.creator; }
159 
161  unsigned int GetPriority() const { return eventpriority; }
162 };
163 
164 inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
165 {
166  return (lhs->GetPriority() < rhs->GetPriority());
167 }
168 
169 inline bool Events::ModuleEventProvider::ElementComp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
170 {
171  if (lhs->GetPriority() < rhs->GetPriority())
172  return true;
173  if (lhs->GetPriority() > rhs->GetPriority())
174  return false;
175  return std::less<ModuleEventListener*>()(lhs, rhs);
176 }
177 
183 #define FOREACH_MOD_CUSTOM(prov, listenerclass, func, params) do { \
184  const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \
185  for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \
186  { \
187  listenerclass* _t = static_cast<listenerclass*>(*_i); \
188  const Module* _m = _t->GetModule(); \
189  if (_m && !_m->dying) \
190  _t->func params ; \
191  } \
192 } while (0);
193 
201 #define FIRST_MOD_RESULT_CUSTOM(prov, listenerclass, func, result, params) do { \
202  result = MOD_RES_PASSTHRU; \
203  const ::Events::ModuleEventProvider::SubscriberList& _handlers = (prov).GetSubscribers(); \
204  for (::Events::ModuleEventProvider::SubscriberList::const_iterator _i = _handlers.begin(); _i != _handlers.end(); ++_i) \
205  { \
206  listenerclass* _t = static_cast<listenerclass*>(*_i); \
207  const Module* _m = _t->GetModule(); \
208  if (!_m || _m->dying) \
209  continue; \
210  result = _t->func params ; \
211  if (result != MOD_RES_PASSTHRU) \
212  break; \
213  } \
214 } while (0);
dynamic_reference_base::SetCaptureHook
void SetCaptureHook(CaptureHook *h)
Definition: dynref.h:52
ServiceProvider
Definition: base.h:249
Events::ModuleEventListener::ModuleEventListener
ModuleEventListener(Module *mod, const std::string &eventid, unsigned int eventprio=DefaultPriority)
Definition: event.h:141
Events::ModuleEventListener::GetPriority
unsigned int GetPriority() const
Definition: event.h:161
dynamic_reference_nocheck
Definition: dynref.h:95
Events::ModuleEventProvider::Unsubscribe
void Unsubscribe(ModuleEventListener *subscriber)
Definition: event.h:78
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:118
Module
Definition: modules.h:247
Events::ModuleEventProvider::GetSubscribers
const SubscriberList & GetSubscribers() const
Definition: event.h:64
Events::ModuleEventListener::GetModule
const Module * GetModule() const
Definition: event.h:158
Events::ModuleEventProvider::Subscribe
void Subscribe(ModuleEventListener *subscriber)
Definition: event.h:69
Events::ModuleEventProvider::ModuleEventProvider
ModuleEventProvider(Module *mod, const std::string &eventid)
Definition: event.h:54