Never had a reason to have multiple ownership.
That's quite possible, since what is required for any particualr application
varies greatly.
Consider, though, if you were a 3D game programmer who wanted to invent an
engine to rival DirectX (I know, blasphemy, I tell you, blasphemy!
You
realize one of the tricks is to have some texture that can be repeated on
multiple walls in the world.
Does it make sense to have each wall object keep a separate copy of the
texture? Even today this would cause the computer and/or graphics to run out
of memory fast. It is better for each wall object to point to the same
bitmap representing the texture. However, you want to support the broadest
base of possibly machines, so you want to dump textures no longer being used
to reduce end-user memory requirements. Part of the scheme should then
include that if an object needs a texure not already in memory it loads it
in. Fair enough?
In this scenario, a wall could easily discover it needs to load in its
texture, and then future walls could make use of it. But the wall that
loaded it in could easily be destroyed while other walls are still making
use of it. So the allocator can't be the destructor.
Ok, then who does destroy the texture when everyone is done with it? Well,
one clever method might be for the allocator to designate to another wall
still using the texture that it be the 'torch carrier' for destroying the
texture. Then when a wall discovers there are no more walls using it, it
might destroy the texture. This is a bit cumbersome, but could be done using
'static' variables to comunicate amongst the walls. Quick note: Notice how
this method requires GLOBALIZING information amongst the walls...
So, when the 'torch carrier' wall can't find another wall to pass the torch
to, it destroys the texture. But wait!!!! We want this application to be
REALLY efficient, so we cleverly allow that same texture to be usable by
other objects in the world: like furniture, posters, helmets, flags, etc. So
now none of the walls in the wall class can destroy the texture, since it is
necessary to know when no object in the system is still using it. Now we
need to derive everything that could use the texture from one class. Gee,
this is getting even more cumbersome, and even more GLOBAL in scope.
Especially since we just used up all our 'inheritance cards' (multiple
inheitance is not universally supported, such as VS.NET CLI). For example,
now you can't have a derived custom Form class that uses the texture since
no class can derive from both our 'texture-aware' underlining class AND Form
at the same time. Bummer.
So, stepping outside the box, and realizing that the entity responsible for
destroying our texture benefits form being as global as it can be, we see
that the best candidate for keeping track of whether or not any object is
still using the texture is the application itself, since it has the largest
scope for the application (DUH!). And when the application takes care of
destroying things that are no longer being used, this is called 'garbage
collecting"! : )
Yes, of course there are ways around these techniques that don't require GC.
Just like there are ways of doing Windows programming in assembly, or
avoiding object-oriented techniques such as creating classes. One could wrap
the allocation/delete methods, keep track of everything allocated and how
many references to each, and destroy anything not already destroyed upon
exit. But that would be just writing your own GC! Why not instead just use
all the tools available to you if they make life easier?
[==P==]
PS - Josh - how would you do the above texture situation WITHOUT maving
multiple ownership of the texture bitmap in memory?
Josh McFarlane said:
Andre said:
But over DLL boundaries you can't pass objects and ownership directly.
And if you have to share code with different languages you have to use
DLLs.
So the GC can see past code that isn't in it's realm, such as native or
VB, or even a shared memory space, or am I confusing what you're trying
to say?
[...]
have that big of a problem with it. I just go with the philosophy of
the allocator owns the pointer, unless it calls another function which
always assumes ownership of the allocated pointer, and that the owner
is responsible for freeing the memory.
[...]
And if there are multiple owners ? E.g. if the object is stored in
multiple lists ? How to keep track of ownership ?
Never had a reason to have multiple ownership. For items that have
program-lifetime, I handle initialization before spawning whatever else
needs it, still own it, and then deconstruct / destroy it at program
shutdown after the dependant objects are destroyed.
Can you give a concrete example of a variable lifetime for an object
dealt with by 2 different threads that doesn't have an inherant race
condition?
Josh McFarlane