]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/base.h
98ce20fd5485feee477181ddd2cb9b4f93e2c0d5
[user/henk/code/inspircd.git] / include / base.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2020 Matt Schatz <genius3000@g3k.solutions>
5  *   Copyright (C) 2013, 2015 Attila Molnar <attilamolnar@hush.com>
6  *   Copyright (C) 2012-2013, 2017, 2020 Sadie Powell <sadie@witchery.services>
7  *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
8  *   Copyright (C) 2012 ChrisTX <xpipe@hotmail.de>
9  *   Copyright (C) 2011-2012 Adam <Adam@anope.org>
10  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
11  *   Copyright (C) 2007 Oliver Lupton <om@inspircd.org>
12  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
13  *   Copyright (C) 2006, 2010 Craig Edwards <brain@inspircd.org>
14  *
15  * This file is part of InspIRCd.  InspIRCd is free software: you can
16  * redistribute it and/or modify it under the terms of the GNU General Public
17  * License as published by the Free Software Foundation, version 2.
18  *
19  * This program is distributed in the hope that it will be useful, but WITHOUT
20  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
22  * details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26  */
27
28
29 #pragma once
30
31 #include "compat.h"
32 #include <string>
33
34 /** Dummy class to help enforce culls being parent-called up to classbase */
35 class CullResult
36 {
37         CullResult();
38         friend class classbase;
39 };
40
41 /** The base class for all inspircd classes with a well-defined lifetime.
42  * Classes that inherit from this may be destroyed through GlobalCulls,
43  * and may rely on cull() being called prior to their deletion.
44  */
45 class CoreExport classbase
46 {
47  public:
48         classbase();
49
50         /**
51          * Called just prior to destruction via cull list.
52          */
53         virtual CullResult cull();
54         virtual ~classbase();
55  private:
56         // uncopyable
57         classbase(const classbase&);
58         void operator=(const classbase&);
59 };
60
61 /** The base class for inspircd classes that provide a wrapping interface, and
62  * should only exist while being used. Prevents heap allocation.
63  */
64 class CoreExport interfacebase
65 {
66  public:
67         interfacebase() {}
68         static inline void* operator new(size_t, void* m) { return m; }
69  private:
70         interfacebase(const interfacebase&);
71         void operator=(const interfacebase&);
72         static void* operator new(size_t);
73         static void operator delete(void*);
74 };
75
76 /** The base class for inspircd classes that support reference counting.
77  * Any objects that do not have a well-defined lifetime should inherit from
78  * this, and should be assigned to a reference<type> object to establish their
79  * lifetime.
80  *
81  * Reference objects should not hold circular references back to themselves,
82  * even indirectly; this will cause a memory leak because the count will never
83  * drop to zero.
84  *
85  * Using a normal pointer for the object is recommended if you can assure that
86  * at least one reference<> will remain as long as that pointer is used; this
87  * will avoid the slight overhead of changing the reference count.
88  */
89 class CoreExport refcountbase
90 {
91         mutable unsigned int refcount;
92  public:
93         refcountbase();
94         virtual ~refcountbase();
95         inline unsigned int GetReferenceCount() const { return refcount; }
96         static inline void* operator new(size_t, void* m) { return m; }
97         static void* operator new(size_t);
98         static void operator delete(void*);
99         inline void refcount_inc() const { refcount++; }
100         inline bool refcount_dec() const { refcount--; return !refcount; }
101  private:
102         // uncopyable
103         refcountbase(const refcountbase&);
104         void operator=(const refcountbase&);
105 };
106
107 /** Base class for use count tracking. Uses reference<>, but does not
108  * cause object deletion when the last user is removed.
109  *
110  * Safe for use as a second parent class; will not add a second vtable.
111  */
112 class CoreExport usecountbase
113 {
114         mutable unsigned int usecount;
115  public:
116         usecountbase() : usecount(0) { }
117         ~usecountbase();
118         inline unsigned int GetUseCount() const { return usecount; }
119         inline void refcount_inc() const { usecount++; }
120         inline bool refcount_dec() const { usecount--; return false; }
121  private:
122         // uncopyable
123         usecountbase(const usecountbase&);
124         void operator=(const usecountbase&);
125 };
126
127 template <typename T>
128 class reference
129 {
130         T* value;
131  public:
132         reference() : value(0) { }
133         reference(T* v) : value(v) { if (value) value->refcount_inc(); }
134         reference(const reference<T>& v) : value(v.value) { if (value) value->refcount_inc(); }
135         reference<T>& operator=(const reference<T>& other)
136         {
137                 if (other.value)
138                         other.value->refcount_inc();
139                 this->reference::~reference();
140                 value = other.value;
141                 return *this;
142         }
143
144         ~reference()
145         {
146                 if (value && value->refcount_dec())
147                         delete value;
148         }
149
150         inline reference<T>& operator=(T* other)
151         {
152                 if (value != other)
153                 {
154                         if (value && value->refcount_dec())
155                                 delete value;
156                         value = other;
157                         if (value)
158                                 value->refcount_inc();
159                 }
160
161                 return *this;
162         }
163
164         inline operator bool() const { return (value != NULL); }
165         inline operator T*() const { return value; }
166         inline T* operator->() const { return value; }
167         inline T& operator*() const { return *value; }
168         inline bool operator<(const reference<T>& other) const { return value < other.value; }
169         inline bool operator>(const reference<T>& other) const { return value > other.value; }
170         static inline void* operator new(size_t, void* m) { return m; }
171  private:
172 #ifndef _WIN32
173         static void* operator new(size_t);
174         static void operator delete(void*);
175 #endif
176 };
177
178 /** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
179  * When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or
180  * a class derived from ModuleException. If a module throws an exception during its constructor, the module will not
181  * be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
182  * attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
183  */
184 class CoreExport CoreException : public std::exception
185 {
186  protected:
187         /** Holds the error message to be displayed
188          */
189         const std::string err;
190         /** Source of the exception
191          */
192         const std::string source;
193
194  public:
195         /** This constructor can be used to specify an error message before throwing.
196          * @param message Human readable error message
197          */
198         CoreException(const std::string &message) : err(message), source("The core") {}
199         /** This constructor can be used to specify an error message before throwing,
200          * and to specify the source of the exception.
201          * @param message Human readable error message
202          * @param src Source of the exception
203          */
204         CoreException(const std::string &message, const std::string &src) : err(message), source(src) {}
205         /** This destructor solves world hunger, cancels the world debt, and causes the world to end.
206          * Actually no, it does nothing. Never mind.
207          * @throws Nothing!
208          */
209         virtual ~CoreException() throw() {}
210         /** Returns the reason for the exception.
211          * @return Human readable description of the error
212          */
213         const std::string& GetReason() const { return err; }
214
215         /** Returns the source of the exception
216          * @return Source of the exception
217          */
218         const std::string& GetSource() const { return source; }
219 };
220
221 class Module;
222 class CoreExport ModuleException : public CoreException
223 {
224  public:
225         /** This constructor can be used to specify an error message before throwing.
226          */
227         ModuleException(const std::string &message, Module* me = NULL);
228 };
229
230 typedef const reference<Module> ModuleRef;
231
232 enum ServiceType {
233         /** is a Command */
234         SERVICE_COMMAND,
235         /** is a ModeHandler */
236         SERVICE_MODE,
237         /** is a metadata descriptor */
238         SERVICE_METADATA,
239         /** is a data processing provider (MD5, SQL) */
240         SERVICE_DATA,
241         /** is an I/O hook provider */
242         SERVICE_IOHOOK,
243         /** Service managed by a module */
244         SERVICE_CUSTOM
245 };
246
247 /** A structure defining something that a module can provide */
248 class CoreExport ServiceProvider : public classbase
249 {
250  public:
251         /** Module that is providing this service */
252         ModuleRef creator;
253         /** Name of the service being provided */
254         const std::string name;
255         /** Type of service (must match object type) */
256         const ServiceType service;
257         ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type);
258         virtual ~ServiceProvider();
259
260         /** Retrieves a string that represents the type of this service. */
261         const char* GetTypeString() const;
262
263         /** Register this service in the appropriate registrar
264          */
265         virtual void RegisterService();
266
267         /** If called, this ServiceProvider won't be registered automatically
268          */
269         void DisableAutoRegister();
270 };