]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/base.cpp
Use custom allocater to decide if refcountbase was allocated on the heap and should...
[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 static const unsigned int top_bit = 1 << (8*sizeof(unsigned int) - 1);
47
48 void* refcountbase::operator new(size_t size)
49 {
50         last_heap = ::operator new(size);
51         return last_heap;
52 }
53
54 void refcountbase::operator delete(void* obj)
55 {
56         if (last_heap == obj)
57                 last_heap = NULL;
58         ::operator delete(obj);
59 }
60
61 refcountbase::refcountbase()
62 {
63         if (this == last_heap)
64                 refcount = 0;
65         else
66                 refcount = top_bit;
67 }
68
69 refcountbase::~refcountbase()
70 {
71         if ((refcount & ~top_bit) && ServerInstance && ServerInstance->Logs)
72                 ServerInstance->Logs->Log("CULLLIST", DEBUG, "refcountbase::~ @%p with refcount %x",
73                         (void*)this, refcount);
74 }
75
76 ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : key(Key), owner(mod)
77 {
78 }
79
80 ExtensionItem::~ExtensionItem()
81 {
82 }
83
84 void* ExtensionItem::get_raw(const Extensible* container) const
85 {
86         Extensible::ExtensibleStore::const_iterator i =
87                 container->extensions.find(const_cast<ExtensionItem*>(this));
88         if (i == container->extensions.end())
89                 return NULL;
90         return i->second;
91 }
92
93 void* ExtensionItem::set_raw(Extensible* container, void* value)
94 {
95         std::pair<Extensible::ExtensibleStore::iterator,bool> rv =
96                 container->extensions.insert(std::make_pair(this, value));
97         if (rv.second)
98         {
99                 return NULL;
100         }
101         else
102         {
103                 void* old = rv.first->second;
104                 rv.first->second = value;
105                 return old;
106         }
107 }
108
109 void* ExtensionItem::unset_raw(Extensible* container)
110 {
111         Extensible::ExtensibleStore::iterator i = container->extensions.find(this);
112         if (i == container->extensions.end())
113                 return NULL;
114         void* rv = i->second;
115         container->extensions.erase(i);
116         return rv;
117 }
118
119 void ExtensionManager::Register(ExtensionItem* item)
120 {
121         types.insert(std::make_pair(item->key, item));
122 }
123
124 void ExtensionManager::BeginUnregister(Module* module, std::vector<reference<ExtensionItem> >& list)
125 {
126         std::map<std::string, reference<ExtensionItem> >::iterator i = types.begin();
127         while (i != types.end())
128         {
129                 std::map<std::string, reference<ExtensionItem> >::iterator me = i++;
130                 ExtensionItem* item = me->second;
131                 if (item->owner == module)
132                 {
133                         list.push_back(item);
134                         types.erase(me);
135                 }
136         }
137 }
138
139 ExtensionItem* ExtensionManager::GetItem(const std::string& name)
140 {
141         std::map<std::string, reference<ExtensionItem> >::iterator i = types.find(name);
142         if (i == types.end())
143                 return NULL;
144         return i->second;
145 }
146
147 void Extensible::doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove)
148 {
149         for(std::vector<reference<ExtensionItem> >::const_iterator i = toRemove.begin(); i != toRemove.end(); ++i)
150         {
151                 ExtensionItem* item = *i;
152                 ExtensibleStore::iterator e = extensions.find(item);
153                 if (e != extensions.end())
154                 {
155                         item->free(e->second);
156                         extensions.erase(e);
157                 }
158         }
159 }
160
161 static struct DummyExtensionItem : LocalExtItem
162 {
163         DummyExtensionItem() : LocalExtItem("", NULL) {}
164         void free(void*) {}
165 } dummy;
166
167 Extensible::Extensible()
168 {
169         extensions[&dummy] = NULL;
170 }
171
172 CullResult Extensible::cull()
173 {
174         for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i)
175         {
176                 i->first->free(i->second);
177         }
178         extensions.clear();
179         return classbase::cull();
180 }
181
182 Extensible::~Extensible()
183 {
184         if (!extensions.empty() && ServerInstance && ServerInstance->Logs)
185                 ServerInstance->Logs->Log("CULLLIST", DEBUG,
186                         "Extensible destructor called without cull @%p", (void*)this);
187 }
188
189 LocalExtItem::LocalExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
190 {
191 }
192
193 LocalExtItem::~LocalExtItem()
194 {
195 }
196
197 std::string LocalExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
198 {
199         return "";
200 }
201
202 void LocalExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
203 {
204 }
205
206 LocalStringExt::LocalStringExt(const std::string& Key, Module* Owner)
207         : SimpleExtItem<std::string>(Key, Owner) { }
208
209 LocalStringExt::~LocalStringExt()
210 {
211 }
212
213 std::string LocalStringExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
214 {
215         if (item && format == FORMAT_USER)
216                 return *static_cast<std::string*>(item);
217         return "";
218 }
219
220 LocalIntExt::LocalIntExt(const std::string& Key, Module* mod) : LocalExtItem(Key, mod)
221 {
222 }
223
224 LocalIntExt::~LocalIntExt()
225 {
226 }
227
228 std::string LocalIntExt::serialize(SerializeFormat format, const Extensible* container, void* item) const
229 {
230         if (format != FORMAT_USER)
231                 return "";
232         return ConvToStr(reinterpret_cast<intptr_t>(item));
233 }
234
235 intptr_t LocalIntExt::get(const Extensible* container) const
236 {
237         return reinterpret_cast<intptr_t>(get_raw(container));
238 }
239
240 intptr_t LocalIntExt::set(Extensible* container, intptr_t value)
241 {
242         if (value)
243                 return reinterpret_cast<intptr_t>(set_raw(container, reinterpret_cast<void*>(value)));
244         else
245                 return reinterpret_cast<intptr_t>(unset_raw(container));
246 }
247
248 void LocalIntExt::free(void*)
249 {
250 }
251
252 StringExtItem::StringExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
253 {
254 }
255
256 StringExtItem::~StringExtItem()
257 {
258 }
259
260 std::string* StringExtItem::get(const Extensible* container) const
261 {
262         return static_cast<std::string*>(get_raw(container));
263 }
264
265 std::string StringExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
266 {
267         return item ? *static_cast<std::string*>(item) : "";
268 }
269
270 void StringExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
271 {
272         if (value.empty())
273                 unset(container);
274         else
275                 set(container, value);
276 }
277
278 void StringExtItem::set(Extensible* container, const std::string& value)
279 {
280         void* old = set_raw(container, new std::string(value));
281         delete static_cast<std::string*>(old);
282 }
283
284 void StringExtItem::unset(Extensible* container)
285 {
286         void* old = unset_raw(container);
287         delete static_cast<std::string*>(old);
288 }
289
290 void StringExtItem::free(void* item)
291 {
292         delete static_cast<std::string*>(item);
293 }
294
295 ModuleException::ModuleException(const std::string &message, Module* who)
296         : CoreException(message, who ? who->ModuleSourceFile : "A Module")
297 {
298 }
299
300 ModuleRef::ModuleRef(Module* v) : value(v)
301 {
302         if (value) inc(value);
303 }
304
305 ModuleRef::~ModuleRef()
306 {
307         if (value) dec(value);
308 }