digitalmars.D.learn - Object cleanup and weak references
- Max Bolingbroke (43/43) Oct 28 2006 Hi,
- Bill Baxter (16/73) Oct 28 2006 Maybe this message from a few days ago helps?
- Max Bolingbroke (12/29) Oct 28 2006 Wow, I have no idea what that code is doing noodling around in Ds
- Max Bolingbroke (7/21) Oct 29 2006 Well, I solved the issue just by blindly adding
- Thomas Kuehne (12/21) Oct 29 2006 -----BEGIN PGP SIGNED MESSAGE-----
- Max Bolingbroke (6/23) Oct 29 2006 Thanks Thomas, it works: I assume this is just to force bud to recognize...
- Lionello Lunesu (7/30) Oct 29 2006 You can force the GC to run a collect: std.gc.fullCollect();
Hi, I was writing a thin wrapper for SDL in D, in which I hoped to do something like the following (very much simplified from real code): static this() { SDL_Init(INIT_EVERYTHING); } static ~this() { SDL_Quit(); } class Surface() { SDL_Surface* handle; public this(char[] filename) { handle = IMG_Load(filename); } ~this() { SDL_FreeSurface(handle); } } It looks great and I don't have to remember to explicitly free my surfaces. However, there are two problems with Ds shutdown process that mean this won't work: 1) In my case the static constructor / destructors were located in a separate "initialize" module, and it turned out that on quit it was being destructed (running SDL_Quit) BEFORE the GC ran and destructed my Surface objects (running SDL_FreeSurface). Clearly we can't Free after we have Quit, so that's problem number 1. 2) Even if I removed the call to SDL_Quit it would still fail with an access violation on SDL_FreeSurface because D has somehow caused it to go away at the point the destructor was run (Anyone know why? I'm using Derelict for the SDL imports, by the way). So, I searched the site and found this guy (http://www.digitalmars.com/d/archives/digitalmars/D/learn/729.html) who was trying to do >exactly< the same thing as me, and had exactly the same problem. I have adopted his solution (an associative array of references that is added to when a Surface is created and systematically disposed in the static destructor before SDL_Quit occurs) and it works nicely, but it means that we have the problem of memory bloat: no Surface can ever be GCed before the program terminates because the array of surfaces to kill off holds a reference to every single one! The perfect solution to this is weak references, but I've done some more searching and found some posts from a few years back saying that apparently D does not support these wonderful things! So, can anyone tell me if this is still true? And if it is, is there another, cleaner, solution to my problem? Thanks for any help, and sorry about the long post! Max
Oct 28 2006
Maybe this message from a few days ago helps? http://www.digitalmars.com/d/archives/digitalmars/D/learn/5016.html It may require wrapping your SDL_Surfaces in wrapper objects, becuase the above doesn't work with structs. Something like: class CSDL_Surface { this(SDL_Surface *s) { surf = s; } ~this() { SDL_FreeSurface(surf); } SDL_Surface *surf; } Then you'll need to always use the class destructor to free surfaces too to maintain 1-1 correspondence between live surfaces and objects. Thomas is probably the only one who can say if it'll work or not, though. --bb Max Bolingbroke wrote:Hi, I was writing a thin wrapper for SDL in D, in which I hoped to do something like the following (very much simplified from real code): static this() { SDL_Init(INIT_EVERYTHING); } static ~this() { SDL_Quit(); } class Surface() { SDL_Surface* handle; public this(char[] filename) { handle = IMG_Load(filename); } ~this() { SDL_FreeSurface(handle); } } It looks great and I don't have to remember to explicitly free my surfaces. However, there are two problems with Ds shutdown process that mean this won't work: 1) In my case the static constructor / destructors were located in a separate "initialize" module, and it turned out that on quit it was being destructed (running SDL_Quit) BEFORE the GC ran and destructed my Surface objects (running SDL_FreeSurface). Clearly we can't Free after we have Quit, so that's problem number 1. 2) Even if I removed the call to SDL_Quit it would still fail with an access violation on SDL_FreeSurface because D has somehow caused it to go away at the point the destructor was run (Anyone know why? I'm using Derelict for the SDL imports, by the way). So, I searched the site and found this guy (http://www.digitalmars.com/d/archives/digitalmars/D/learn/729.html) who was trying to do >exactly< the same thing as me, and had exactly the same problem. I have adopted his solution (an associative array of references that is added to when a Surface is created and systematically disposed in the static destructor before SDL_Quit occurs) and it works nicely, but it means that we have the problem of memory bloat: no Surface can ever be GCed before the program terminates because the array of surfaces to kill off holds a reference to every single one! The perfect solution to this is weak references, but I've done some more searching and found some posts from a few years back saying that apparently D does not support these wonderful things! So, can anyone tell me if this is still true? And if it is, is there another, cleaner, solution to my problem? Thanks for any help, and sorry about the long post! Max
Oct 28 2006
Bill Baxter wrote:Maybe this message from a few days ago helps? http://www.digitalmars.com/d/archives/digitalmars/D/learn/5016.html It may require wrapping your SDL_Surfaces in wrapper objects, becuase the above doesn't work with structs. Something like: class CSDL_Surface { this(SDL_Surface *s) { surf = s; } ~this() { SDL_FreeSurface(surf); } SDL_Surface *surf; } Then you'll need to always use the class destructor to free surfaces too to maintain 1-1 correspondence between live surfaces and objects. Thomas is probably the only one who can say if it'll work or not, though.Wow, I have no idea what that code is doing noodling around in Ds internals, but if it works I will be a very happy man. Unfortunately, my project fails to compile after adding this code: F:\Programming\Current\Destroyed>bud main -cleanup -debug -g -I.\..\;D:\D\dmd\src\ext -of.\bin\Destroyed.exe -w D:\D\dmd\src\phobos\internal\gc\gcx.d(42): module win32 cannot read file 'win32.d' Although it seems that win32.d lives in the same directory as gcx.d... can someone point out what newbie mistake am I making? :-) Thanks a lot for your help Bill! Max
Oct 28 2006
Max Bolingbroke wrote: > Wow, I have no idea what that code is doing noodling around in Dsinternals, but if it works I will be a very happy man. Unfortunately, my project fails to compile after adding this code: F:\Programming\Current\Destroyed>bud main -cleanup -debug -g -I.\..\;D:\D\dmd\src\ext -of.\bin\Destroyed.exe -w D:\D\dmd\src\phobos\internal\gc\gcx.d(42): module win32 cannot read file 'win32.d' Although it seems that win32.d lives in the same directory as gcx.d... can someone point out what newbie mistake am I making? :-) Thanks a lot for your help Bill! MaxWell, I solved the issue just by blindly adding -ID:\D\dmd\src\phobos\internal\gc\ to my DMD options: I have no idea why this would be required, but it works a treat now! I owe a debt of gratitude to Thomas for his awesome code :-). Max
Oct 29 2006
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Max Bolingbroke schrieb am 2006-10-29:Wow, I have no idea what that code is doing noodling around in Ds internals, but if it works I will be a very happy man. Unfortunately, my project fails to compile after adding this code: F:\Programming\Current\Destroyed>bud main -cleanup -debug -g -I.\..\;D:\D\dmd\src\ext -of.\bin\Destroyed.exe -w D:\D\dmd\src\phobos\internal\gc\gcx.d(42): module win32 cannot read file 'win32.d' Although it seems that win32.d lives in the same directory as gcx.d... can someone point out what newbie mistake am I making? :-)add import internal.gc.win32; You might have to try different import sequences. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFFRI2kLK5blCcjpWoRAh8eAJ9P3OoJHnQQbTUh4xlUq3ml9W5R2wCcDEY2 HXZYcGeBjnuydlYnD9m1mWo= =VDPQ -----END PGP SIGNATURE-----
Oct 29 2006
Thomas Kuehne wrote:Max Bolingbroke schrieb am 2006-10-29:Thanks Thomas, it works: I assume this is just to force bud to recognize that that file needs to be compiled in? Bit strange that it doesn't pick it up automagically, anyhow.. Thanks again for your help and awesome code :-) MaxWow, I have no idea what that code is doing noodling around in Ds internals, but if it works I will be a very happy man. Unfortunately, my project fails to compile after adding this code: F:\Programming\Current\Destroyed>bud main -cleanup -debug -g -I.\..\;D:\D\dmd\src\ext -of.\bin\Destroyed.exe -w D:\D\dmd\src\phobos\internal\gc\gcx.d(42): module win32 cannot read file 'win32.d' Although it seems that win32.d lives in the same directory as gcx.d... can someone point out what newbie mistake am I making? :-)add import internal.gc.win32; You might have to try different import sequences.
Oct 29 2006
"Max Bolingbroke" <"batterseapower{no" sp4/\\/\\}hotmail.com> wrote in message news:ei0dnr$lv$1 digitaldaemon.com...Hi, I was writing a thin wrapper for SDL in D, in which I hoped to do something like the following (very much simplified from real code): static this() { SDL_Init(INIT_EVERYTHING); } static ~this() { SDL_Quit(); } class Surface() { SDL_Surface* handle; public this(char[] filename) { handle = IMG_Load(filename); } ~this() { SDL_FreeSurface(handle); } } It looks great and I don't have to remember to explicitly free my surfaces. However, there are two problems with Ds shutdown process that mean this won't work: 1) In my case the static constructor / destructors were located in a separate "initialize" module, and it turned out that on quit it was being destructed (running SDL_Quit) BEFORE the GC ran and destructed my Surface objects (running SDL_FreeSurface). Clearly we can't Free after we have Quit, so that's problem number 1.You can force the GC to run a collect: std.gc.fullCollect(); Try doing that in the static ~this. Of course, if there are any pointers (or values looking like pointers!) in memory pointing to a surface object, that object would still not get deleted, causing an exception. L.
Oct 29 2006