On Mon, 07 May 2012 19:00:22 -0400, Mehrdad <[email protected]> wrote:
On Monday, 7 May 2012 at 21:07:15 UTC, Steven Schveighoffer wrote:
I guess I don't really understand that. Who is responsible for
cleaning up your class instance? The way I was understanding your
description, I thought it was the C window runtime calling a callback
you provide to it. Why do you need to have the GC clean it up?
Ah, I see why that's confusing.
Here's a (hopefully better) explanation:
Just as with any other object that represents an outside resource (e.g.
a File/Stream/whatever), the lifetime of the unmanaged object should
always follow the lifetime of the managed object.
In other words, this means that the creation of a Window object MUST be
associated with the system call CreateWindow() (which in turns calls the
window dispatcher function, WndProc, with the message WM_CREATE).
And, more importantly, this means that if the GC collects the Window
object, then DestroyWindow() MUST be called on the kernel object, so
that the window handle doesn't get leaked.
Just as with any other resource.
The trouble is that, as-is, this behavior is NOT implementable with a
simple Window class whose constructor calls CreateWindow() and whose
destructor calls DestroyWindow().
Why? Because if you were to do that in the constructor or destructor,
the system would call back your WndProc() function, which is a *virtual*
function meant to be overridden in the derived classes (so that they can
handle events, such as the creation/destruction of the window, or the
calculation of the window size, etc. properly).
That would mean your WndProc() in the derived instance would be called
*before* the constructor of the derived instance is called, which is
obviously not what you want.
OK, I understand what you are saying now.
What about using NVI?
class Window
{
protected void processMessage_impl(int message) // virtual call
{}
final public void processMessage(int message)
{
if(message == WM_CREATE)
{
// handle specially
}
else if(message == WM_DELETE)
{
// handle specially
}
else
{
processMessage_impl(int message);
}
}
private HWND window;
this()
{
window = CreateWindow(&processMessage); // or whatever mechanism, you
get the idea
}
~this()
{
DestroyWindow(window);
}
}
-Steve