February 2008


Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Sean Luke <[log in to unmask]>
Reply To:
MASON Multiagent Simulation Toolkit <[log in to unmask]>
Wed, 13 Feb 2008 18:54:25 -0500
text/plain (92 lines)
On Feb 13, 2008, at 3:41 AM, Siamak Sarmady wrote:

> Hello,
> In one of my programs I am just using the Display component of Mason.
> The problem is that when I close Display window, program continues to
> run in Background. What else should I do to terminate the entire
> program? (Is it the state object which remains in memory?)

This is a question with a very complex answer, and it's not easy to  
answer given the hack that you're doing here.  So some background.   
When you press "play" on the Console, here's what it does in short:

1. Calls start() on the GUIState (which in turn calls start() on the  
underlying SimState)
2. Spawns a thread (the "play thread") which:
	2a. Blocks waiting for all Swing Events to have completed (using  
	2b.  Loops:
		2b.i. calls simulation.step() to step the simulation once.  This  
automatically synchronizes on the schedule until the step is completed.
		2b.ii. Blocks until all Swing Events have completed

When we try (from the Swing event thread) to repaint the window or  
inspect an object in the window or modify a feature of an object, we  
first synchronize on the underlying Schedule.  This causes us to  
block until the playThread's call of simulation.step() has completed,  
so we don't modify or read bad stuff on the model.

When you call "stop" on the Console we:

1. Interrupt the play thread (since we were called via a java event  
-- mouse click on stop button -- we know we have control and the  
underlying thread is blocking waiting for our Swing Event to complete.

2. Kill the play thread

3. Call finish() on the GUIState

[Keep in mind that you should call init() on the GUIState and also  
quit() on it when you first create it and later destroy it at the end  
of your application.]

The important item to note here is that MASON's GUI facilities are  
designed to hand off a baton and forth between an underlying thread  
(called the "play thread") and Swing.  Whoever has the baton is  
allowed to read/write the model and the schedule, otherwise they have  
to wait.  Waiting for and acquiring the baton is easy: just  
synchronize on the Schedule.

It looks like you are deviating from this model in two ways:

1. You're not handing off the baton.  This could result in race  
conditions you don't want to see.
2. Your model thread (the equivalent of the "play thread" above) is  
the underlying main() thread perhaps?  It's not made clear.   
Ordinarily in Java GUI applications, the main thread just sets things  
up and dies.

The easiest way to handle this is to NOT call start(), but rather let  
the console handle it for you.  Just call console.pressPlay() to  
start the simulation, and console.pressStop() to stop the  
simulation.  You really ought to do these from the GUI thread, not  
the main thread.  If you're not in the GUI thread, you can still do  
this by creating a small Runnable, whose sole function in life is to  
call console.pressPlay(), and adding him to SwingUtilities with a  
SwingUtilities.invokeAndWait(...).  Likewise for console.pressStop().

When the Display2D's window is disposed, by default it calls  
Display2D.quit() first.  But note that in Java by default when you  
click on a close box in a window, it doesn't dispose the window.  It  
just hides it.  That's what MASON is relying on -- it's just hiding  
the window.  You can change the behavior of closing the window to  
actually dispose the window (and thus call quit()), look at JFrame's  
documentation.  Basically, let Display2D create its window with  
createFrame(), and then change that frame's close-box behavior.

If you do this, you will also want to hook into JFrame's quit()  
method to quit your program when the window is closed.  The quick and  
dirty, ugly way to do this is to just override the quit() method in  
Display2D to call System.exit(0).  That will kill everything  
immediately and quit your application.  A better approach would be to  
call console.doClose(), which will cleanly shut down and dispose  

Good luck!  Beware that multithreading coding in Swing is  
nontrivial!  :-)