How would I adapt the hot reloading technique used in HmH to an online game where I want to be able to have two instances of the game running at once in the same machine? As I understand it, the hot reloading worked by copying the main dll of the game into temp.dll at startup, and then when you detect that the main dll changed, unload temp.dll, overwrite it with the new main dll, and load it again. Of course, this doesn't work with two instances running at once, because the first one to try to replace temp.dll will be unable to do so because the other one is still using it.
The simplest solution I can imagine is this:
Is this solution reasonable or is there a simpler/better way of doing this?
If loading the dll loads it into memory, I think the API should allow deleting/overwriting the dll file after that. I understand that assuming that the file won't change simplifies loading the same dll multiple times in one process, but I don't see why they can't allow telling the API "hey, I won't be loading this in multiple threads of this process, so just forget about the file".
Why don't you just copy to Temp1.dll and Temp2.dll
If you don't know if you are 1 or 2 either you check which one already exists or you copy to temp_randomNumber1.dll and temp_randomNumber2.dll
If it's not an issue for you and you have a way to differentiate between the different instances, you could have each instance create its own copy of the dll with a different name (e.g.: the first instance would create temp_1.dll
, the second instance would create temp_2.dll
).
If loading the dll loads it into memory, I think the API should allow deleting/overwriting the dll file after that. I understand that assuming that the file won't change simplifies loading the same dll multiple times in one process, but I don't see why they can't allow telling the API "hey, I won't be loading this in multiple threads of this process, so just forget about the file".
I'm assuming you want to delete the file while you are still using the code (meaning you haven't called FreeLibrary
for that dll). I'm not sure (I'm really not sure) but I think that by keeping the file on disk, the dll image memory doesn't count toward the virtual memory commit limit, meaning that if Windows need memory and decide to page out you program into pagefile.sys
, it will not put the dll in there as it knows it can load it from the disk.
That could work. Unload, try to copy to temp1.dll, else try to copy to temp2.dll, and load again. I forgot to say that eventually I might want to test more than two at once, so it would be nice if it worked with more... But your idea would still work: just keep trying increasing the number (maybe up to 10). Thank you both for the idea :)
About the explanation on why you can't delete/overwrite the dll file: it makes sense, but I still see no clear reason why they couldn't give you the option to tell the API that you want to give up this possibility of not copying to pagefile.sys and relying on the file. However, I guess you could also say "Why can't you delete a .exe while running it, if it's loaded in memory?", which to me seems intuitive but I also don't see why not. Maybe it's for safety, so you have the guarantee that you can identify the original executable of any running process/module from task manager or a debugger.
To run multiple instances I would create string based on process id - something like temp_817238.dll
with GetProcessId(), which will be guaranteed to be unique for your process. Then detect when temp.dll changed and copy that to your process unique dll to load.
Good idea, too, but I think I prefer bumping the number because your idea requires deleting the dll file on close, and since the main use of this is debugging, I can't rely on it terminating normally.
Have your build script delete all temp_*.dll
files - whichever it can. If it cannot then meh, leave them - next time it will be able to delete them.
There are fancier things you can do - like read .dll file to memory and then "load" it from memory. But that will interfere with debugging (won't work at all). Here's a good example code showing how to do that: https://github.com/fancycode/MemoryModule
That's a good idea, too, but it won't work for beta-testers in the future.
Thanks for sharing that GitHub project, too. Reading its documentation cleared my understanding of how dll's work ( https://github.com/fancycode/MemoryModule/tree/master/doc ). This option would be overkill in my case, but it's good to know it can be done.