]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/base.cpp
Use ServiceProvider for inter-module dependencies
[user/henk/code/inspircd.git] / src / base.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd_config.h"
15 #include "base.h"
16 #include <time.h>
17 #include "inspircd.h"
18 #include <typeinfo>
19
20 classbase::classbase()
21 {
22         if (ServerInstance && ServerInstance->Logs)
23                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::+ @%p", (void*)this);
24 }
25
26 CullResult classbase::cull()
27 {
28         if (ServerInstance && ServerInstance->Logs)
29                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::-%s @%p",
30                         typeid(*this).name(), (void*)this);
31         return CullResult();
32 }
33
34 classbase::~classbase()
35 {
36         if (ServerInstance && ServerInstance->Logs)
37                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::~ @%p", (void*)this);
38 }
39
40 CullResult::CullResult()
41 {
42 }
43
44 // This trick detects heap allocations of refcountbase objects
45 static void* last_heap = NULL;
46
47 void* refcountbase::operator new(size_t size)
48 {
49         last_heap = ::operator new(size);
50         return last_heap;
51 }
52
53 void refcountbase::operator delete(void* obj)
54 {
55         if (last_heap == obj)
56                 last_heap = NULL;
57         ::operator delete(obj);
58 }
59
60 refcountbase::refcountbase() : refcount(0)
61 {
62         if (this != last_heap)
63                 throw CoreException("Reference allocate on the stack!");
64 }
65
66 refcountbase::~refcountbase()
67 {
68         if (refcount && ServerInstance && ServerInstance->Logs)
69                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "refcountbase::~ @%p with refcount %d",
70                         (void*)this, refcount);
71 }
72
73 usecountbase::~usecountbase()
74 {
75         if (usecount && ServerInstance && ServerInstance->Logs)
76                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "usecountbase::~ @%p with refcount %d",
77                         (void*)this, usecount);
78 }
79
80 ServiceProvider::~ServiceProvider()
81 {
82 }
83
84 ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : ServiceProvider(mod, Key, SERVICE_METADATA)
85 {
86 }
87
88 ExtensionItem::~ExtensionItem()
89 {
90 }
91
92 void* ExtensionItem::get_raw(const Extensible* container) const
93 {
94         Extensible::ExtensibleStore::const_iterator i =
95                 container->extensions.find(const_cast<ExtensionItem*>(this));
96         if (i == container->extensions.end())
97                 return NULL;
98         return i->second;
99 }
100
101 void* ExtensionItem::set_raw(Extensible* container, void* value)
102 {
103         std::pair<Extensible::ExtensibleStore::iterator,bool> rv =
104                 container->extensions.insert(std::make_pair(this, value));
105         if (rv.second)
106         {
107                 return NULL;
108         }
109         else
110         {
111                 void* old = rv.first->second;
112                 rv.first->second = value;
113                 return old;
114         }
115 }
116
117 void* ExtensionItem::unset_raw(Extensible* container)
118 {
119         Extensible::ExtensibleStore::iterator i = container->extensions.find(this);
120         if (i == container->extensions.end())
121                 return NULL;
122         void* rv = i->second;
123         container->extensions.erase(i);
124         return rv;
125 }
126
127 void ExtensionManager::Register(ExtensionItem* item)
128 {
129         types.insert(std::make_pair(item->name, item));
130 }
131
132 void ExtensionManager::BeginUnregister(Module* module, std::vector<reference<ExtensionItem> >& list)
133 {
134         std::map<std::string, reference<ExtensionItem> >::iterator i = types.begin();
135         while (i != types.end())
136         {
137                 std::map<std::string, reference<ExtensionItem> >::iterator me = i++;
138                 ExtensionItem* item = me->second;
139                 if (item->creator == module)
140                 {
141                         list.push_back(item);
142                         types.erase(me);
143                 }
144         }
145 }
146
147 ExtensionItem* ExtensionManager::GetItem(const std::string& name)
148 {
149         std::map<std::string, reference<ExtensionItem> >::iterator i = types.find(name);
150         if (i == types.end())
151                 return NULL;
152         return i->second;
153 }
154
155 void Extensible::doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove)
156 {
157         for(std::vector<reference<ExtensionItem> >::const_iterator i = toRemove.begin(); i != toRemove.end(); ++i)
158         {
159                 ExtensionItem* item = *i;
160                 ExtensibleStore::iterator e = extensions.find(item);
161                 if (e != extensions.end())
162                 {
163                         item->free(e->second);
164                         extensions.erase(e);
165                 }
166         }
167 }
168
169 static struct DummyExtensionItem : LocalExtItem
170 {
171         DummyExtensionItem() : LocalExtItem("", NULL) {}
172         void free(void*) {}
173 } dummy;
174
175 Extensible::Extensible()
176 {
177         extensions[&dummy] = NULL;
178 }
179
180 CullResult Extensible::cull()
181 {
182         for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i)
183         {
184                 i->first->free(i->second);
185         }
186         extensions.clear();
187         return classbase::cull();
188 }
189
190 Extensible::~Extensible()
191 {
192         if (!extensions.empty() && ServerInstance && ServerInstance->Logs)
193                 ServerInstance->Logs->Log("CULLLIST", DEBUG,
194                         "Extensible destructor called without cull @%p", (void*)this);
195 }
196
197 LocalExtItem::LocalExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
198 {
199 }
200
201 LocalExtItem::~LocalExtItem()
202 {
203 }
204
205 std::string LocalExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
206 {
207         return "";
208 }
209
210 void LocalExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
211 {
212 }
213
214 LocalStringExt::LocalStringExt(const std::string& Key, Module* Owner)
215         : SimpleExtItem<std::string>(Key, Owner) { }
216
217 LocalStringExt::~LocalStringExt()
218 {
219 }
220
221 std::string LocalStringExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
222 {
223         if (item && format == FORMAT_USER)
224                 return *static_cast<std::string*>(item);
225         return "";
226 }
227
228 LocalIntExt::LocalIntExt(const std::string& Key, Module* mod) : LocalExtItem(Key, mod)
229 {
230 }
231
232 LocalIntExt::~LocalIntExt()
233 {
234 }
235
236 std::string LocalIntExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
237 {
238         if (format != FORMAT_USER)
239                 return "";
240         return ConvToStr(reinterpret_cast<intptr_t>(item));
241 }
242
243 intptr_t LocalIntExt::get(const Extensible* container) const
244 {
245         return reinterpret_cast<intptr_t>(get_raw(container));
246 }
247
248 intptr_t LocalIntExt::set(Extensible* container, intptr_t value)
249 {
250         if (value)
251                 return reinterpret_cast<intptr_t>(set_raw(container, reinterpret_cast<void*>(value)));
252         else
253                 return reinterpret_cast<intptr_t>(unset_raw(container));
254 }
255
256 void LocalIntExt::free(void*)
257 {
258 }
259
260 StringExtItem::StringExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
261 {
262 }
263
264 StringExtItem::~StringExtItem()
265 {
266 }
267
268 std::string* StringExtItem::get(const Extensible* container) const
269 {
270         return static_cast<std::string*>(get_raw(container));
271 }
272
273 std::string StringExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
274 {
275         return item ? *static_cast<std::string*>(item) : "";
276 }
277
278 void StringExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
279 {
280         if (value.empty())
281                 unset(container);
282         else
283                 set(container, value);
284 }
285
286 void StringExtItem::set(Extensible* container, const std::string& value)
287 {
288         void* old = set_raw(container, new std::string(value));
289         delete static_cast<std::string*>(old);
290 }
291
292 void StringExtItem::unset(Extensible* container)
293 {
294         void* old = unset_raw(container);
295         delete static_cast<std::string*>(old);
296 }
297
298 void StringExtItem::free(void* item)
299 {
300         delete static_cast<std::string*>(item);
301 }
302
303 ModuleException::ModuleException(const std::string &message, Module* who)
304         : CoreException(message, who ? who->ModuleSourceFile : "A Module")
305 {
306 }
307