On Thu, 2006-08-03 at 13:10 -0400, Thomas Fitzsimmons wrote:

> the three exit conditions are:
> 
>      * There are no displayable AWT or Swing components.
>      * There are no native events in the native event queue.
>      * There are no AWT events in java EventQueues.
> 
> The first two conditions are satisfied by quitting the GTK main thread (no 
> native events) when there are no windows left (no displayable AWT or Swing 
> components).  I'm wondering if we need a check for the third condition before 
> quitting the GTK main loop.

Right, 1) is what I just implemented. As for 2), calling gtk_main_quit()
doesn't quit immediately but rather "Makes the innermost invocation of
the main loop return when it regains control." as the GTK docs say. 
So I'm 95% sure that's to be interpreted as the native queue being empty
at that point.

Condition 3) Is also fulfilled. The EventDispatchThread shuts itself
down as it should, and I'm certain we don't need to check with the GTK
thread. The way I read it, the first two points relate only to the main
GTK thread, and the third point only to the EventDispatchThread. 

So basically when 1) and 2) are satisfied we can shut down the GTK
thread (since the peers are disposed of at that point, the EventQueue
can't call into them and cause new native events). There's no apparent 
reason why we'd need or want to shut them all down at the same time.

Once the GTK thread is shut down the EventQueue empties itself and then
shuts down. It seems to work just fine. I'm attaching a little testcase
that creates and destroys some windows and prints the number of active
threads. As expected we have two; the main GTK thread and the
EventDispatchThread.

Interestingly, the testcase shows that the 1.4 JDK revs up 6 (!)
threads by then. (But 'only' 4 on the 1.5 JDK). I dunno what it's
doing with all those extra threads. Running a botnet? :)

/Sven
import java.awt.*;

public class ThreadTest
{
  public static void main(String[] args)
  {
    System.out.println("Thread initially active:"+Thread.activeCount());
    Frame f = new Frame();
    f.setSize(100,100);
    f.setVisible(true);
    System.out.println("Active after opening window:"+Thread.activeCount());
    long t = System.currentTimeMillis();
    System.out.println("Delaying 5s");
    while( (System.currentTimeMillis() - t) < 5000 )
      Thread.yield();
    System.out.println("Active now:"+Thread.activeCount());
    System.out.println("Disposing peers.");
    f.dispose();
    f = null;    
    t = System.currentTimeMillis();
    System.out.println("Active now::"+Thread.activeCount());
    System.out.println("Waiting 5 s");
    while( (System.currentTimeMillis() - t) < 5000 )
      Thread.yield();
    f = new Frame();
    f.setSize(100,100);
    System.out.println("Recreating peers.");
    f.setVisible(true);
    System.out.println("# of active threads now:"+Thread.activeCount());
    System.out.println("End.");
  }
}

Reply via email to