}
};
+class Module;
+
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() {};
+ ModuleException(const std::string &message, Module* me = NULL);
+};
+
+class CoreExport ModuleRef : public reference_base
+{
+ Module* const value;
+ public:
+ ModuleRef(Module* v);
+ ~ModuleRef();
+ inline operator Module*() const { return value; }
+ inline Module* operator->() const { return value; }
+ inline Module& operator*() const { return *value; }
+ private:
+ ModuleRef(const ModuleRef&);
+ void operator=(const ModuleRef&);
+ void* operator new(size_t);
+ void operator delete(void*);
};
#endif
const std::string command;
/** Creator module - never NULL */
- Module* const creator;
+ ModuleRef creator;
/** User flags needed to execute the command or 0
*/
/**
* Pointer to creator module (if any, or NULL)
*/
- Module* Creator;
+ ModuleRef Creator;
/**
* The input data, either a host or an IP address
*/
{
public:
const std::string key;
- Module* const owner;
+ ModuleRef owner;
ExtensionItem(const std::string& key, Module* owner);
virtual ~ExtensionItem();
/** Serialize this item into a string
public:
/** Module that created this mode. NULL for core modes */
- Module* const creator;
+ ModuleRef creator;
/** Long-form name
*/
const std::string name;
ModeType m_type;
public:
- Module* const creator;
+ ModuleRef creator;
/**
* The constructor initializes the mode and the mode type
*/
/** If you change the module API in any way, increment this value.
* This MUST be a pure integer, with no parenthesis
*/
-#define API_VERSION 135
+#define API_VERSION 136
class ServerConfig;
/** This is a pointer to the sender of the message, which can be used to
* directly trigger events, or to create a reply.
*/
- Module* const source;
+ ModuleRef source;
/** The single destination of the Request
*/
- Module* const dest;
+ ModuleRef dest;
/** Create a new Request
* This is for the 'new' way of defining a subclass
/** This is a pointer to the sender of the message, which can be used to
* directly trigger events, or to create a reply.
*/
- Module* const source;
+ ModuleRef source;
/** The event identifier.
* This is arbitary text which should be used to distinguish
* one type of event from another.
*/
class CoreExport Module : public classbase
{
+ unsigned int refcount;
+ friend class reference_base;
public:
/** File that this module was loaded from
*/
{
delete static_cast<std::string*>(item);
}
+
+ModuleException::ModuleException(const std::string &message, Module* who)
+ : CoreException(message, who ? who->ModuleSourceFile : "A Module")
+{
+}
+
+ModuleRef::ModuleRef(Module* v) : value(v)
+{
+ if (value) inc(value);
+}
+
+ModuleRef::~ModuleRef()
+{
+ if (value) dec(value);
+}
// These declarations define the behavours of the base class Module (which does nothing at all)
-Module::Module() { }
+Module::Module() : refcount(0) { }
CullResult Module::cull()
{
return classbase::cull();
}
-Module::~Module() { }
+Module::~Module()
+{
+ if (refcount)
+ ServerInstance->Logs->Log("MODULE", DEFAULT, "References remain to destructed module " + ModuleSourceFile);
+}
ModResult Module::OnSendSnotice(char &snomask, std::string &type, const std::string &message) { return MOD_RES_PASSTHRU; }
void Module::OnUserConnect(User*) { }