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 | |
4 | #include <base/system.h> |
5 | |
6 | #include <engine/kernel.h> |
7 | |
8 | #include <vector> |
9 | |
10 | class CKernel : public IKernel |
11 | { |
12 | class CInterfaceInfo |
13 | { |
14 | public: |
15 | CInterfaceInfo() : |
16 | m_pInterface(nullptr), |
17 | m_AutoDestroy(false) |
18 | { |
19 | m_aName[0] = '\0'; |
20 | } |
21 | |
22 | CInterfaceInfo(const char *pName, IInterface *pInterface, bool AutoDestroy) : |
23 | m_pInterface(pInterface), |
24 | m_AutoDestroy(AutoDestroy) |
25 | { |
26 | str_copy(dst&: m_aName, src: pName); |
27 | } |
28 | |
29 | char m_aName[64]; |
30 | IInterface *m_pInterface; |
31 | bool m_AutoDestroy; |
32 | }; |
33 | |
34 | std::vector<CInterfaceInfo> m_vInterfaces; |
35 | |
36 | CInterfaceInfo *FindInterfaceInfo(const char *pName) |
37 | { |
38 | for(CInterfaceInfo &Info : m_vInterfaces) |
39 | { |
40 | if(str_comp(a: pName, b: Info.m_aName) == 0) |
41 | return &Info; |
42 | } |
43 | return nullptr; |
44 | } |
45 | |
46 | public: |
47 | CKernel() = default; |
48 | |
49 | void Shutdown() override |
50 | { |
51 | for(int i = (int)m_vInterfaces.size() - 1; i >= 0; --i) |
52 | { |
53 | if(m_vInterfaces[i].m_AutoDestroy) |
54 | { |
55 | m_vInterfaces[i].m_pInterface->Shutdown(); |
56 | } |
57 | } |
58 | } |
59 | |
60 | ~CKernel() override |
61 | { |
62 | // delete interfaces in reverse order just the way it would happen to objects on the stack |
63 | for(int i = (int)m_vInterfaces.size() - 1; i >= 0; --i) |
64 | { |
65 | if(m_vInterfaces[i].m_AutoDestroy) |
66 | { |
67 | delete m_vInterfaces[i].m_pInterface; |
68 | m_vInterfaces[i].m_pInterface = nullptr; |
69 | } |
70 | } |
71 | } |
72 | |
73 | void RegisterInterfaceImpl(const char *pName, IInterface *pInterface, bool Destroy) override |
74 | { |
75 | dbg_assert(str_length(pName) < (int)sizeof(CInterfaceInfo().m_aName), "Interface name too long" ); |
76 | dbg_assert(FindInterfaceInfo(pName) == nullptr, "Duplicate interface name" ); |
77 | |
78 | pInterface->m_pKernel = this; |
79 | m_vInterfaces.emplace_back(args&: pName, args&: pInterface, args&: Destroy); |
80 | } |
81 | |
82 | void ReregisterInterfaceImpl(const char *pName, IInterface *pInterface) override |
83 | { |
84 | dbg_assert(FindInterfaceInfo(pName) != nullptr, "Cannot reregister interface that is not registered" ); |
85 | pInterface->m_pKernel = this; |
86 | } |
87 | |
88 | IInterface *RequestInterfaceImpl(const char *pName) override |
89 | { |
90 | CInterfaceInfo *pInfo = FindInterfaceInfo(pName); |
91 | dbg_assert(pInfo != nullptr, "Interface not found" ); |
92 | return pInfo->m_pInterface; |
93 | } |
94 | }; |
95 | |
96 | IKernel *IKernel::Create() { return new CKernel; } |
97 | |