| 1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
| 2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
| 3 | #ifndef ENGINE_KERNEL_H |
| 4 | #define ENGINE_KERNEL_H |
| 5 | |
| 6 | class IKernel; |
| 7 | class IInterface; |
| 8 | |
| 9 | class IInterface |
| 10 | { |
| 11 | // friend with the kernel implementation |
| 12 | friend class CKernel; |
| 13 | IKernel *m_pKernel; |
| 14 | |
| 15 | protected: |
| 16 | IKernel *Kernel() { return m_pKernel; } |
| 17 | |
| 18 | public: |
| 19 | IInterface() : |
| 20 | m_pKernel(nullptr) {} |
| 21 | virtual void Shutdown() {} |
| 22 | virtual ~IInterface() = default; |
| 23 | }; |
| 24 | |
| 25 | #define MACRO_INTERFACE(Name) \ |
| 26 | public: \ |
| 27 | static const char *InterfaceName() { return Name; } \ |
| 28 | \ |
| 29 | private: |
| 30 | |
| 31 | // This kernel class makes the structure very flat and basically singletons. |
| 32 | // I'm not sure if this is a good idea but it works for now. |
| 33 | class IKernel |
| 34 | { |
| 35 | // hide the implementation |
| 36 | virtual void RegisterInterfaceImpl(const char *pInterfaceName, IInterface *pInterface, bool Destroy) = 0; |
| 37 | virtual void ReregisterInterfaceImpl(const char *pInterfaceName, IInterface *pInterface) = 0; |
| 38 | virtual IInterface *RequestInterfaceImpl(const char *pInterfaceName) = 0; |
| 39 | |
| 40 | public: |
| 41 | static IKernel *Create(); |
| 42 | virtual void Shutdown() = 0; |
| 43 | virtual ~IKernel() = default; |
| 44 | |
| 45 | // templated access to handle pointer conversions and interface names |
| 46 | template<class TINTERFACE> |
| 47 | void RegisterInterface(TINTERFACE *pInterface, bool Destroy = true) |
| 48 | { |
| 49 | RegisterInterfaceImpl(pInterfaceName: TINTERFACE::InterfaceName(), pInterface, Destroy); |
| 50 | } |
| 51 | template<class TINTERFACE> |
| 52 | void ReregisterInterface(TINTERFACE *pInterface) |
| 53 | { |
| 54 | ReregisterInterfaceImpl(pInterfaceName: TINTERFACE::InterfaceName(), pInterface); |
| 55 | } |
| 56 | |
| 57 | // Usage example: |
| 58 | // IMyInterface *pMyHandle = Kernel()->RequestInterface<IMyInterface>() |
| 59 | template<class TINTERFACE> |
| 60 | TINTERFACE *RequestInterface() |
| 61 | { |
| 62 | return reinterpret_cast<TINTERFACE *>(RequestInterfaceImpl(pInterfaceName: TINTERFACE::InterfaceName())); |
| 63 | } |
| 64 | }; |
| 65 | |
| 66 | #endif |
| 67 | |