From: Ashley Ward <ashley@dcs.warwick.ac.uk>
To: Meurig Beynon <wmb@dcs.warwick.ac.uk>
Subject: Re: Lift stuff
Date: Wed, 1 Oct 2003 21:47:17 +0100

On Wednesday, October 1, 2003, at 08:44  am, Meurig Beynon wrote:
> /dcs/acad/wmb/public/projects/simulations/LIFT/LUCERNE

OK... I've had a look and I've got a reasonable understanding of why 
tkeden is behaving as it is with this model.

***

The quick answer: I think you'll be a lot more satisfied with it if you 
add an eager() to the delay procedure, as below:

   proc delay {
           para delaytime;
           auto ft0, ft;
           ft0 = ftime()[1];
           ft = ft0;
           while ((ft - ft0) < delaytime) {ft = ftime()[1]; eager();}
   }

***

The long answer:

Eden is a sequential, singly threaded machine.  There's only one thing 
executing at a time.  Here's an example interaction with ttyeden:

   8|> for (i = 1; i < 1000000; i++) { };
   writeln("hi");
   9|> writeln("hi");
   hi

Whilst the for loop was executing, I typed writeln("hi"); on the second 
line, and ttyeden ignored it (the echoing of my typing is done by the 
OS -- well, actually the terminal libraries, I think).  When ttyeden 
was finally ready for me, it read the buffered input, shown on the 
third line, and runs it.

So whilst a procedural block is executing, Eden doesn't do anything 
else.  This includes loops like above, also blocks of code in procs and 
funcs, also calls that procs or funcs make to other procs or funcs, 
also procs that are triggered by change.  When all these things have 
terminated, the machine is in a "consistent" state and Eden stops 
executing and deals with input.

Now tkeden.  The GUI interface is actually driven by Tk.  Tk only gets 
a chance to do interface tasks when Eden calls the Tk "update" routine. 
  When this is called, Tk updates the screen display with any changes, 
reads input from the input window, deals with mouse clicks etc.  If 
Eden doesn't call the Tk update routine, none of these things happen, 
and the interface "freezes".  Eden doesn't call this routine whilst it 
is executing a procedural block of code etc: see above.

The exception to these rules described so far is eager().  Calls to 
eager evaluate the formula queue and then call the Tk update routine.

In ttyeden, this has no effect, because ttyeden doesn't use Tk for 
input / output handling (and actually the call to Tk update is 
conditionally compiled out in ttyeden).

   12|> for (i = 1; i < 1000000; i++) { eager(); };
   writeln("hi");
   13|> writeln("hi");
   hi

In tkeden, saying this in the input window freezes the interface until 
control-c is pressed (note even pressing the Interrupt button doesn't 
work because this relies on the Tk update routine to function):

   while (1) { };

However, saying this allows the interface to continue "normally":

   while (1) { eager(); };

... although from the point of entering this command onwards, the Eden 
machine is actually continuously executing an eager loop (repeated 
calling the Tk update routine).  Notice that the messages after 
pressing the Interrupt button after running this line say that the 
RunSets have been cleared... pressing the Interrupt button normally 
just acknowledges that the button has been pressed.

***

The above may help you right now.  A "proper" solution is much more in 
depth and will require discussion about what you are actually 
expecting.  It seems to me that you want the machine to pause when 
variables mentioned in keylist are changed.  But I don't think that's 
realistic: this solution causes all agents to be paused, including the 
user input, because Eden is a sequential, singly threaded machine.

1 procmacro playlift {
2        _liftfloor = 3;
3        if (commentary) {
4                writeln("\TRAVAILS IN A LIFT");
5                writeln("\nX, Y and I wait for lift\n");
6        }
7        locX = locY = locI = 1;
8        destX = destI = 4;

What's actually going on here:

line 2: change to _liftfloor triggers keylist, causes delay.
between 2 + 3: my procmacro code has inserted an eager, so screen 
updates and user input is allowed
line 3, 4, 5, 6: possibly an eager between each of these lines
line 7: locX, then locY, then locI (or possibly the other way around 
depending on precedence) trigger keylist and cause 3 calls to delay.
between 7 and 8: a call to eager, so it looks like your line 7 was 
"atomic" (although see my comments for line 7: it isn't, at that level 
of consideration).
line 8: doesn't trigger keylist, so no delay
after line 8: call to eager...

We could rewrite as something like

proc playlift {
         _liftfloor = 3;
         if (commentary) {
                 writeln("\TRAVAILS IN A LIFT");
                 writeln("\nX, Y and I wait for lift\n");
         }
         delay(1);
         locX = locY = locI = 1;
         delay(1);
         destX = destI = 4;

... but we still have the problem that user input isn't allowed during 
delay() (unless you insert eager() as I suggest).

Perhaps ultimately we need to store a list of transitions that you want 
to make here possibly with information about pauses, and have a 
procedure that goes something like (pseudo-code):

proc nextinstruction {
   if enough time has elapsed since the last instruction:
     look up next instruction in list
     execute() it

   todo("nextinstruction();");
}

Hum.

Or really it needs rethinking in terms of my PhD notions of multiple 
agents, each with their own "atomicity" of view.

...


(the suggested change to the delay() procedure has been made in the
liftBeynon2003 model).

Ashley
October 2003
