Subject: Re: Request for power testers

From: Roger Crew <[email-masked]>
Date: Fri, 18 Dec 1992 15:08:25 -0800

Looking over the new code, if I'm reading things right, it appears that

TRY
  <try-body>
FINALLY
  <finally-portion>
ENDTRY

is a form of unwind-protect, i.e., the finally-portion of the body
always gets executed no matter what errors occur in the main try-body,
unless something does a kill_task() or we run out of ticks.

It looks to me like it would be fairly straightforward to subtract n
ticks from the clock on entering the try-body (in EOP_TRY_FINALLY).
At the end of the try-body (EOP_END_TRY_FINALLY) or any unwinding of
the stack one would then restore those n ticks.  Then the
finally-portion would be guaranteed at least n ticks to run even if
the try-body runs out of ticks.  The idea here is that if there are
fewer than n ticks left when you get to the beginning of the TRY, then
you abort immediately with "out of ticks" (thus penalizing you for
beeing greedy --- one only reserves what one thinks one will need).

The handler entry on the stack would have to include a
number-of-ticks-to-restore field and you'd also be keeping track of
the total number of reserved ticks in any given task so that if the
task suspends, the reserved ticks can be subtracted from the 15000 (?)
that the newly-resumed task would ordinarily get when it resumes.
This way

(*) a background task would never be running with a tick allowance
   higher than 15000.

(*) once you reserve n ticks, those ticks stay reserved whether or not
   the task later suspends --- the ticks only go back when the handler
   gets popped off the stack (i.e., on a normal exit for the try body,
   or an exception that reaches that handler)

n could just be a constant (e.g., 500), or you could modify the syntax 
slightly:

TRY
  ...
FINALLY (300)
  (i.e, we'll say this section needs no more than 300 ticks to run)
  ...
ENDTRY

Another thought would be that the usual kill_task() be reinterpreted:

   Set ticks_left to 0 so that the next time the task attempts
   to run it dies.  Also set a flag to indicate that this really was a
   kill_task and not an ordinary out-of-ticks, so that we don't get a 
   backtrace.

The difference from before is that any pending finally sections will run 
(with only the allotment of ticks they had reserved on try-entry) to do
any cleanups that might be necessary.  

This would mostly fix the current problem in which any player's code 
I call can screw me by doing one of the following:

   1) divide_by_zero or some other random error 
         catchable by TRY...EXCEPT/FINALLY
   2) exhausting the tick/second clock
         would be catchable if TRY...FINALLY can reserve ticks
   3) issuing a kill_task(task_id())
         catchable if TRY...FINALLY can reserve ticks and
         kill_task() is simply a ticks_left := 0 operation;
   4) suspend() 
         (needs more thought ... see below)

We might conceivably still need a terminate-with-extreme-prejuidice function
for use by wizards.

vaporize_task() 
   set the tick clock to some suitably negative-infinite number. 
   Task dies immediately and no finally-sections get to run.
   (granted, this could be implemented the way kill-task currently is, since
   the effect is the same).

About catching suspends:

Given the above, one could try to fake this with
  TRY ... FINALLY (15000) ... ENDTRY 
since any suspend would result in an out-of-ticks that would
then unwind back to this finally section.  Admittedly, what
you really want is a way to get the finally clause to execute 
*before* the suspension takes place.  e.g.,
 TRY ... ONSUSPEND ... ENDTRY

An alternative would be a construct making suspend() a no-op for 
the duration of a particular statement or expression.

A third alternative would be a construct allowing one to specify
suspend hooks and resume hooks, e.g.,

CRITICAL
  <statements>
ONSUSPEND
  <prepare-for-hibernation code...>
ONRESUME
  <look-at-new-state-of-the-world code...>
ENDCRITICAL

it's rather annoying that statements and expressions are different
things, since we'd really need one of these constructs for each.

--
Roger Crew
Internet:   [email-masked]
LambdaMOO:  Rog

---

From: Roger Crew <[email-masked]>
Date: Fri, 18 Dec 1992 15:08:25 -0800

TRY
  <try-body>
FINALLY
  <finally-portion>
ENDTRY

TRY
  ...
FINALLY (300)

vaporize_task() 

About catching suspends:

CRITICAL
  <statements>
ONSUSPEND

---

From: Pavel Curtis <[email-masked]>
Date: Fri, 18 Dec 1992 17:07:33 -0800

For most of you, Roger's message must not make any sense; it was sent in
response to a message I sent to him with much smaller distribution.

	Pavel