Multihead and shutting down displays



My goal for this week is to get the multihead API to the point 
where I'm happy with it for 2.2, and put out a 2.1.x release.

By far the most important outstanding issue for multihead is
how to shut down a display and release resources associated
with it; below is a proposal for how things should work.

Thanks for any feedback on this,
                                        Owen

Introduction
============

This capability is extremely important for several applications
of multihead support:

 A) Application migration support
 B) A single component serving widgets to multiple displays.

Also, being to shut down single-head GDK is a frequent request;
usually people want this want this when checking for memory
leaks at program exit. (The other reason is that people
want to be able to unload a dynamic module using GDK; shutting
down GDK doesn't actually help because of type system issues.)

Issues that make shutting down displays tricky:

 * There may be outstanding GObjects that are associated with
   the display, such as GdkWindow, GdkPixmap, GdkGC objects.

   We can't simply free these objects; an object must never
   be freed as long as it has outstanding refcounts.

   GdkWindow is a special case. It has a somewhat
   peculiar memory management scheme. GdkWindow is a GObject
   with two special reference counts:

    - One reference count is held by GTK+ until gtk_window_destroy()
      is called on the window.

      (Note that calling gtk_window_destroy() on the parent
      of a window doesn't release this reference count; 
      gdk_window_destroy() must be called exactly once
      on each individual window; similarly.)

      [ This reference count doesn't exist for foreign windows ]

    - One reference count is held (for X11) by the XID table
      that maps X ids to windows ids. This is not released
      until the DestroyNotify for the window is received.

 * There are a large number of singleton objects associated
   with a display that are not currently memory managed; some
   of them being:

    - Visuals
    - The system colormap
    - The key map
    - GtkClipboard 
    - Input device (GdkDevice)

 * In many places, we cache data associated with a display;
   just a few examples in GTK+:
  
    - The GC cache in gtkgc.c
    - "IPC widgets" and cursors in gtkdnd.c
    - Bitmaps for widget parts in gtkstyle.c
   

The proposal
============

My proposal for how things should work is as follows:

 * GdkDisplay, and all it's associated singletons should
   all work as follows:

    - There is a single refcount owned by GTK+ that exists
      as long as the display is open.

    - When the display is closed by gdk_display_close()
      GTK+ drops its own refcounts and calls g_object_run_dispose()
      on the display and all singleton objects.

 * We keep track of all GDK objects associated with the 
   display, and when the display is closed, mark them
   all as invalid. An attempt to use such an object silently
   does nothing.

 * Caches should use g_object_weak_ref() to keep track of
   when the display is closed and free objects.
 
 * Closing a GdkDisplay does *not* obviate the need
   to call gdk_window_destroy() on the window. This 
   is parallel to the fact that you still need to 
   call gdk_window_destroy() on the window if you
   destroy its parent.

   It does, however, mark the window destroyed.

   [ Actually, from an implementation point of view,
     since the window is marked destroyed by 
     gdk_display_close(), you could then use 
     g_object_unref() rather than gdk_window_destroy(),
     but I think it's best to say "always call
     gdk_window_destroy() exactly once". ]

 * Once Xlib is fixed, If we detect that an IO error occurred,
   or that the connection to the display was lost, we
   mark all GDK objects associated with the display, but
   _do not_ act as if gdk_display_close() was called; we
   leave that to the app. 

   (GdkDisplay should, however, have a signal indicating 
   that such an error occurred.)


Other rejected approaches
=========================

 * We could make all singleton and other objects refcount the
   display so that as long as anybody held a refcount to
   the display, the display was kept open. 

   Problems with this:

    - It could make closing the display really hard, since
      a single existing object would prevent closing the
      display.

    - We'd still need to have "shutting down" notification to
      deal with caches of objects for the display.

    - In general, reference counting should have no user-visible
      effects beyond memory management; keeping a display open is a 
      "user-visible effect", because the user can't terminate
      the display without killing the program.


Open questions/issues
=====================

 * g_object_weak_ref() is a somewhat inconvenient notification
   mechanism because g_object_get_data() can't be used within the weak
   reference callback. 

   This shouldn't *usually* matter, since the data that would be
   stored as object data can be passed as the 'data' argument to
   g_object_weak_ref().

   It's possible that we should add a a signal similar to 
   GtkObject::destroy to simplify things for users.

 * Is it really necesary to call g_object_run_dispose() on
   GdkVisual, GdkDevice objects? Probably not, but I guess
   conceptually simplest.

   The concept is that one of the following always holds:

    -  Memory management of the object is handled by the app,
       and apps should use g_object_ref()/unref().
       (GdkWindow, GdkPixmap, GdkGC, etc.)

    -  Memory management of the object is handled by GTK+
       and apps should use g_object_weak_ref().

 * Should we also call g_object_run_dispose() on non-singleton 
   objects? We don't currently do it on gdk_window_destroy().



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]