ddnet/src/engine/kernel.h
Robert Müller 0c6978f553 Support arbitrary number of kernel interfaces, assert on errors
Support registering arbitrary number of interfaces with `IKernel` instead at most 32.

Assert when incorrect arguments are passed to `IKernel` functions instead of returning a `bool`, which was not being handled in all cases. These functions are not expected to fail expect on programming errors.

Consistently order and format creation and registration of kernel interfaces in client and server.
2023-12-04 18:11:47 +01:00

69 lines
1.8 KiB
C++

/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#ifndef ENGINE_KERNEL_H
#define ENGINE_KERNEL_H
#include <base/system.h>
class IKernel;
class IInterface;
class IInterface
{
// friend with the kernel implementation
friend class CKernel;
IKernel *m_pKernel;
protected:
IKernel *Kernel() { return m_pKernel; }
public:
IInterface() :
m_pKernel(nullptr) {}
virtual void Shutdown() {}
virtual ~IInterface() {}
};
#define MACRO_INTERFACE(Name) \
public: \
static const char *InterfaceName() { return Name; } \
\
private:
// This kernel thingie makes the structure very flat and basically singletons.
// I'm not sure if this is a good idea but it works for now.
class IKernel
{
// hide the implementation
virtual void RegisterInterfaceImpl(const char *pInterfaceName, IInterface *pInterface, bool Destroy) = 0;
virtual void ReregisterInterfaceImpl(const char *pInterfaceName, IInterface *pInterface) = 0;
virtual IInterface *RequestInterfaceImpl(const char *pInterfaceName) = 0;
public:
static IKernel *Create();
virtual void Shutdown() = 0;
virtual ~IKernel() {}
// templated access to handle pointer conversions and interface names
template<class TINTERFACE>
void RegisterInterface(TINTERFACE *pInterface, bool Destroy = true)
{
RegisterInterfaceImpl(TINTERFACE::InterfaceName(), pInterface, Destroy);
}
template<class TINTERFACE>
void ReregisterInterface(TINTERFACE *pInterface)
{
ReregisterInterfaceImpl(TINTERFACE::InterfaceName(), pInterface);
}
// Usage example:
// IMyInterface *pMyHandle = Kernel()->RequestInterface<IMyInterface>()
template<class TINTERFACE>
TINTERFACE *RequestInterface()
{
return reinterpret_cast<TINTERFACE *>(RequestInterfaceImpl(TINTERFACE::InterfaceName()));
}
};
#endif