Doxygen Samurai Engine 0.0.1
Doxygen Samurai Engine Documentation
Loading...
Searching...
No Matches
dllLoader.cpp
Go to the documentation of this file.
1#include "dllLoader.h"
2#include "Config.h"
3#include <unordered_set>
4
5static std::filesystem::path dllPath = std::filesystem::current_path();
6
7#ifdef SAMURAI_DEVELOPMENT
8
9 #ifdef SAMURAI_WINDOWS
10
11 #define NOMINMAX
12 #include <Windows.h>
13
14 static FILETIME getLastWriteFile(const char *name)
15 {
16 FILETIME time = {};
17
18 WIN32_FILE_ATTRIBUTE_DATA Data = {};
19 if (GetFileAttributesEx(name, GetFileExInfoStandard, &Data))
20 {
21 time = Data.ftLastWriteTime;
22 }
23 else
24 {
25 return {};
26 }
27
28 return(time);
29 }
30
31 #endif
32
33
34#endif
35
36
37void samurai::LoadedDll::reloadContainerExtensionsSupport()
38{
39#pragma region reload extension support
40 {
41 containerExtensionsSupport.clear();
42 for (auto &c : containerInfo)
43 {
44 for (auto &e : c.containerStaticInfo.extensionsSuported)
45 {
46 containerExtensionsSupport[e.to_string()] = c.containerName;
47 }
48 }
49 }
50#pragma endregion
51}
52
53bool samurai::LoadedDll::constructRuntimeContainer(RuntimeContainer &c, const char *name)
54{
55 SAMURAI_DEVELOPMENT_ONLY_ASSERT(constructContainer_ != nullptr, "dll not loaded");
56 return constructContainer_(&c.pointer, &c.arena, name);
57}
58
59
60
61void samurai::LoadedDll::bindAllocatorDllRealm(samurai::memory::CustomAllocator *allocator)
62{
63 SAMURAI_DEVELOPMENT_ONLY_ASSERT(bindAllocator_ != nullptr, "dll not loaded");
64 bindAllocator_(allocator);
65}
66
67void samurai::LoadedDll::resetAllocatorDllRealm()
68{
69 SAMURAI_DEVELOPMENT_ONLY_ASSERT(resetAllocator_ != nullptr, "dll not loaded");
70 resetAllocator_();
71}
72
73void samurai::LoadedDll::getContainerInfoAndCheck(samurai::LogManager &logs)
74{
75 containerInfo.clear();
76 containerInfo.reserve(100);
77
78 //todo check for valid containers
79 getContainersInfo_(containerInfo);
80
81 std::unordered_set<std::string> uniqueNames = {};
82
83 for (int i = 0; i < containerInfo.size(); i++)
84 {
85 auto signalError = [&](const char *e)
86 {
87 std::string l = e + containerInfo[i].containerName;
88 logs.log(l.c_str(), samurai::logError);
89
90 containerInfo.erase(containerInfo.begin() + i);
91 i--;
92 };
93
94 if (uniqueNames.find(containerInfo[i].containerName) == uniqueNames.end())
95 {
96 uniqueNames.insert(containerInfo[i].containerName);
97 }
98 else
99 {
100 signalError("Duplicate container name: ");
101 continue;
102 }
103
104 if (containerInfo[i].containerStaticInfo._internalNotImplemented)
105 {
106 signalError("Container did not implement containerInfo function: ");
107 continue;
108 }
109
110 if (containerInfo[i].containerStaticInfo.defaultHeapMemorySize < 100)
111 {
112 signalError("Too little heap memory for container: ");
113 continue;
114 }
115
116 }
117}
118
119
120
121
122bool samurai::LoadedDll::loadDll(int id, samurai::LogManager &logs)
123{
124 unloadDll();
125
126
127 std::filesystem::path originalDll = dllPath / "gameplay.dll";
128 std::filesystem::path copyDll = dllPath / ( "gameplayCopy" + std::to_string(id) + ".dll");
129
130 filetime = getLastWriteFile(originalDll.string().c_str());
131
132 if (filetime.dwLowDateTime == FILETIME().dwLowDateTime
133 &&
134 filetime.dwHighDateTime == FILETIME().dwHighDateTime
135 ) { return false; }
136
137
138 //std::filesystem::copy(originalDll, copyDll, std::filesystem::copy_options::overwrite_existing);
139 if (!CopyFile(originalDll.string().c_str(), copyDll.string().c_str(), false) ) { return false; }
140
141
142 dllHand = LoadLibraryA(copyDll.string().c_str());
143
144 if (!dllHand) { return false; }
145
146 gameplayStart_ = (gameplayStart_t *)GetProcAddress(dllHand, "gameplayStart");
147 gameplayReload_ = (gameplayReload_t *)GetProcAddress(dllHand, "gameplayReload");
148 getContainersInfo_ = (getContainersInfo_t *)GetProcAddress(dllHand, "getContainersInfo");
149 constructContainer_ = (constructContainer_t *)GetProcAddress(dllHand, "constructContainer");
150 destructContainer_ = (destructContainer_t *)GetProcAddress(dllHand, "destructContainer");
151 bindAllocator_ = (bindAllocator_t *)GetProcAddress(dllHand, "bindAllocator");
152 resetAllocator_ = (resetAllocator_t *)GetProcAddress(dllHand, "resetAllocator");
153 dissableAllocators_ = (dissableAllocators_t *)GetProcAddress(dllHand, "dissableAllocators");
154
155 if (!gameplayStart_) { return false; }
156 if (!gameplayReload_) { return false; }
157 if (!getContainersInfo_) { return false; }
158 if (!constructContainer_) { return false; }
159 if (!destructContainer_) { return false; }
160 if (!bindAllocator_) { return false; }
161 if (!resetAllocator_) { return false; }
162 if (!dissableAllocators_) { return false; }
163
164 //get container info
165 getContainerInfoAndCheck(logs);
166 this->id = id;
167
168 reloadContainerExtensionsSupport();
169
170 return true;
171}
172
173bool samurai::LoadedDll::checkIfDllIsOpenable()
174{
175 HANDLE fileCheck = {};
176 fileCheck = CreateFile((dllPath / "gameplay.dll").string().c_str(),
177 GENERIC_READ | GENERIC_WRITE, NULL, NULL,
178 OPEN_EXISTING, 0, NULL);
179
180 if (fileCheck == INVALID_HANDLE_VALUE)
181 {
182 return false;
183 }
184 else
185 {
186 CloseHandle(fileCheck);
187 return true;
188 }
189}
190
191bool samurai::LoadedDll::tryToloadDllUntillPossible(int id, samurai::LogManager &logs,
192 std::chrono::duration<long long> timeout)
193{
194 auto startTime = std::chrono::steady_clock::now();
195
196 while (!checkIfDllIsOpenable())
197 {
198 if (timeout != std::chrono::seconds(0))
199 {
200 if (std::chrono::steady_clock::now() > startTime + timeout)
201 {
202 return false; //timeout
203 }
204 }
205 //Wait till the dll can be oppened. It is possible that the compiler still keeps it busy.
206 }
207
208 unloadDll();
209
210
211 //try to load (we loop since it is still possible that windows thinks that the dll is not available yet)
212 while (!loadDll(id, logs))
213 {
214 if (timeout != std::chrono::seconds(0))
215 {
216 if (std::chrono::steady_clock::now() > startTime + timeout)
217 {
218 return false; //timeout
219 }
220 }
221 };
222 return true;
223}
224
225void samurai::LoadedDll::unloadDll()
226{
227 if (dllHand == 0) { return; }
228
229 //dissableAllocators_();
230
231 resetAllocatorDllRealm();
232
233 FreeLibrary(dllHand);
234 dllHand = {};
235 filetime = {};
236 containerInfo.clear();
237}
238
239bool samurai::LoadedDll::shouldReloadDll()
240{
241 if (dllHand == 0) { return 0; }
242
243 std::filesystem::path originalDll = dllPath / "gameplay.dll";
244
245 FILETIME newFiletime = getLastWriteFile(originalDll.string().c_str());
246
247 if (filetime.dwLowDateTime == FILETIME().dwLowDateTime
248 &&
249 filetime.dwHighDateTime == FILETIME().dwHighDateTime
250 )
251 {
252 return false;
253 }
254
255 return (CompareFileTime(&filetime, &newFiletime) != 0);
256}
257
static std::filesystem::path dllPath
Definition dllLoader.cpp:5
@ logError
Definition log.h:12
void log(const char *l, int type=samurai::logNormal)
Definition log.cpp:14