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

Reply via email to