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









Max Bolingbroke <"batterseapower{no" sp4/\\/\\}hotmail.com> 