summaryrefslogtreecommitdiff
path: root/include/base.h
blob: ed03eeac5313c45e15d975005ffc8b8e72e3e9df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*       +------------------------------------+
 *       | Inspire Internet Relay Chat Daemon |
 *       +------------------------------------+
 *
 *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
 * See: http://wiki.inspircd.org/Credits
 *
 * This program is free but copyrighted software; see
 *            the file COPYING for details.
 *
 * ---------------------------------------------------
 */

#ifndef __BASE_H__
#define __BASE_H__

#include <map>
#include <deque>
#include <string>

/** The base class for all inspircd classes.
 * Wherever possible, all classes you create should inherit from this,
 * giving them the ability to be passed to various core functions
 * as 'anonymous' classes.
*/
class CoreExport classbase
{
 public:
	classbase();

	/**
	 * Called just prior to destruction via cull list.
	 *
	 * @return true to allow the delete, or false to halt the delete
	 */
	virtual bool cull();
	virtual ~classbase();
};

/** The base class for inspircd classes that support reference counting.
 * Any objects that do not have a well-defined lifetime should inherit from
 * this
 */
class CoreExport refcountbase : public classbase
{
	unsigned int refcount;
 public:
	refcountbase();
	virtual bool cull();
	virtual ~refcountbase();
	inline unsigned int GetReferenceCount() const { return refcount; }
	friend class reference_base;
};

class CoreExport reference_base
{
 protected:
	template<typename T> static inline unsigned int inc(T* v) { return ++(v->refcount); }
	template<typename T> static inline unsigned int dec(T* v) { return --(v->refcount); }
};

template <typename T>
class reference : public reference_base
{
	T* value;
 public:
	reference() : value(0) { }
	reference(T* v) : value(v) { if (value) inc(value); }
	reference(const reference& v) : value(v.value) { if (value) inc(value); }
	reference<T>& operator=(const reference<T>& other)
	{
		if (other.value)
			inc(other.value);
		this->reference::~reference();
		value = other.value;
		return *this;
	}

	~reference()
	{
		if (value)
		{
			int rc = dec(value);
			if (rc == 0 && value->cull())
				delete value;
		}
	}
	inline const T* operator->() const { return value; }
	inline const T& operator*() const { return *value; }
	inline T* operator->() { return value; }
	inline T& operator*() { return *value; }
	inline operator bool() const { return value; }
	inline operator T*() const { return value; }
};

/** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
 * When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or
 * a class derived from ModuleException. If a module throws an exception during its constructor, the module will not
 * be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
 * attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
 */
class CoreExport CoreException : public std::exception
{
 protected:
	/** Holds the error message to be displayed
	 */
	const std::string err;
	/** Source of the exception
	 */
	const std::string source;
 public:
	/** Default constructor, just uses the error mesage 'Core threw an exception'.
	 */
	CoreException() : err("Core threw an exception"), source("The core") {}
	/** This constructor can be used to specify an error message before throwing.
	 */
	CoreException(const std::string &message) : err(message), source("The core") {}
	/** This constructor can be used to specify an error message before throwing,
	 * and to specify the source of the exception.
	 */
	CoreException(const std::string &message, const std::string &src) : err(message), source(src) {}
	/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
	 * Actually no, it does nothing. Never mind.
	 * @throws Nothing!
	 */
	virtual ~CoreException() throw() {};
	/** Returns the reason for the exception.
	 * The module should probably put something informative here as the user will see this upon failure.
	 */
	virtual const char* GetReason()
	{
		return err.c_str();
	}

	virtual const char* GetSource()
	{
		return source.c_str();
	}
};

class CoreExport ModuleException : public CoreException
{
 public:
	/** Default constructor, just uses the error mesage 'Module threw an exception'.
	 */
	ModuleException() : CoreException("Module threw an exception", "A Module") {}

	/** This constructor can be used to specify an error message before throwing.
	 */
	ModuleException(const std::string &message) : CoreException(message, "A Module") {}
	/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
	 * Actually no, it does nothing. Never mind.
	 * @throws Nothing!
	 */
	virtual ~ModuleException() throw() {};
};

#endif