Hot reloading with multiple running instances

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:

  • When you try to overwrite temp.dll, allow failure. In that case, keep trying regularly, and also check if temp.dll's last edited time is after the last edited time of the original dll (that means someone else has overwritten it). Don't try to call the dll's procedures (the game code) until you've overwritten temp.dll succeessfully, or temp.dll's last edited time is higher than the original dll's, and loaded temp.dll successfully.

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.


Edited by Simon Anciaux on Reason: typo

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.


Edited by Opoiregwfetags on
Replying to mrmixer (#26179)

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.


Edited by Mārtiņš Možeiko on
Replying to Opoiregwfetags (#26180)

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.


Replying to mmozeiko (#26181)

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


Edited by Mārtiņš Možeiko on

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.


Replying to mmozeiko (#26183)