InspIRCd  4.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  : public ServiceProvider
40 {
41  public:
42  struct Comp
43  {
44  bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const;
45  };
46 
47  struct ElementComp
48  {
49  bool operator()(ModuleEventListener* lhs, ModuleEventListener* rhs) const;
50  };
51 
53 
58  ModuleEventProvider(Module* mod, const std::string& eventid)
59  : ServiceProvider(mod, eventid, SERVICE_DATA)
60  , prov(mod, eventid)
61  {
62  prov.SetCaptureHook(this);
63  }
64 
66  const Module* GetModule() const { return prov.creator; }
67 
71  const SubscriberList& GetSubscribers() const { return prov->subscribers; }
72 
76  void Subscribe(ModuleEventListener* subscriber)
77  {
78  subscribers.insert(subscriber);
79  OnSubscribe(subscriber);
80  }
81 
85  void Unsubscribe(ModuleEventListener* subscriber)
86  {
87  subscribers.erase(subscriber);
88  OnUnsubscribe(subscriber);
89  }
90 
92  template<typename Class, typename... FunArgs, typename... FwdArgs>
93  inline void Call(void (Class::*function)(FunArgs...), FwdArgs&&... args) const;
94 
99  template<typename Class, typename... FunArgs, typename... FwdArgs>
100  inline ModResult FirstResult(ModResult (Class::*function)(FunArgs...), FwdArgs&&... args) const;
101 
102  private:
103  void OnCapture() override
104  {
105  // If someone else holds the list from now on, clear mine. See below for more info.
106  if (*prov != this)
107  subscribers.clear();
108  }
109 
113  virtual void OnSubscribe(ModuleEventListener* subscriber) { }
114 
118  virtual void OnUnsubscribe(ModuleEventListener* subscriber) { }
119 
126 
130  SubscriberList subscribers;
131 };
132 
137 {
141 
142  const unsigned int eventpriority;
143 
146  void OnCapture() override
147  {
148  prov->Subscribe(this);
149  }
150 
151  public:
152  static const unsigned int DefaultPriority = 100;
153 
159  ModuleEventListener(Module* mod, const std::string& eventid, unsigned int eventprio = DefaultPriority)
160  : prov(mod, eventid)
161  , eventpriority(eventprio)
162  {
163  prov.SetCaptureHook(this);
164  // If the dynamic_reference resolved at construction our capture handler wasn't called
165  if (prov)
166  ModuleEventListener::OnCapture();
167  }
168 
170  {
171  if (prov)
172  prov->Unsubscribe(this);
173  }
174 
176  const Module* GetModule() const { return prov.creator; }
177 
179  unsigned int GetPriority() const { return eventpriority; }
180 };
181 
182 inline bool Events::ModuleEventProvider::Comp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
183 {
184  return (lhs->GetPriority() < rhs->GetPriority());
185 }
186 
187 inline bool Events::ModuleEventProvider::ElementComp::operator()(Events::ModuleEventListener* lhs, Events::ModuleEventListener* rhs) const
188 {
189  if (lhs->GetPriority() < rhs->GetPriority())
190  return true;
191  if (lhs->GetPriority() > rhs->GetPriority())
192  return false;
193  return std::less<ModuleEventListener*>()(lhs, rhs);
194 }
195 
196 template<typename Class, typename... FunArgs, typename... FwdArgs>
197 inline void Events::ModuleEventProvider::Call(void (Class::*function)(FunArgs...), FwdArgs&&... args) const
198 {
199  if (GetModule() && GetModule()->dying)
200  return;
201 
202  for (const auto& subscriber : subscribers)
203  {
204  const Module* mod = subscriber->GetModule();
205  if (!mod || mod->dying)
206  continue;
207 
208  Class* klass = static_cast<Class*>(subscriber);
209  (klass->*function)(std::forward<FwdArgs>(args)...);
210  }
211 }
212 
213 template<typename Class, typename... FunArgs, typename... FwdArgs>
214 inline ModResult Events::ModuleEventProvider::FirstResult(ModResult (Class::*function)(FunArgs...), FwdArgs&&... args) const
215 {
216  if (GetModule() && GetModule()->dying)
217  return MOD_RES_PASSTHRU;
218 
219  ModResult result;
220  for (const auto& subscriber : subscribers)
221  {
222  const Module* mod = subscriber->GetModule();
223  if (!mod || mod->dying)
224  continue;
225 
226  Class* klass = static_cast<Class*>(subscriber);
227  result = (klass->*function)(std::forward<FwdArgs>(args)...);
228  if (result != MOD_RES_PASSTHRU)
229  break;
230  }
231  return result;
232 }
Definition: event.h:137
ModuleEventListener(Module *mod, const std::string &eventid, unsigned int eventprio=DefaultPriority)
Definition: event.h:159
const Module * GetModule() const
Definition: event.h:176
unsigned int GetPriority() const
Definition: event.h:179
Definition: event.h:40
ModuleEventProvider(Module *mod, const std::string &eventid)
Definition: event.h:58
void Subscribe(ModuleEventListener *subscriber)
Definition: event.h:76
const SubscriberList & GetSubscribers() const
Definition: event.h:71
const Module * GetModule() const
Definition: event.h:66
ModResult FirstResult(ModResult(Class::*function)(FunArgs...), FwdArgs &&... args) const
Definition: event.h:214
void Unsubscribe(ModuleEventListener *subscriber)
Definition: event.h:85
void Call(void(Class::*function)(FunArgs...), FwdArgs &&... args) const
Definition: event.h:197
Definition: modules.h:72
Definition: modules.h:286
bool dying
Definition: modules.h:320
Definition: base.h:204
void SetCaptureHook(CaptureHook *h)
Definition: dynref.h:54
Definition: dynref.h:98
Definition: event.h:43