Proposed Change to when/latch/catch Expansion Mark S. Miller (markm@caplet.com)
Sat, 22 Jan 2000 18:30:15 -0800

Currently,

     when(r) -> done(foo) {
         good
     } catch problem {
         bad
      }

expands to

     r <- whenResolved(define done {
         to run(temp1) : void {
             if (E isBroken(temp1)) {
                 define problem := E optProblem(temp1)
                 bad
             } else {
                 define foo := temp1
                 good
             }
         }

})

which captures well what has become the standard idiom for using whenResolved. However, in looking through the site (using the new navigation controls), http://www.erights.org/elang/concurrency/race.html reminded me on a subtle principle-of-least-authority issue I got right early on, but then forgot. As a result, it didn't make it into the standard idiom, and was thereby not captured by the when/latch/catch construct.

The issue is shown by the use of "once" in "asynchAnd" to guard against the recipient of a whenResolved invoking the observer multiple times. Although possible, it would be burdensome and accident prone to insist that the programmer code when/latch/catch bodies so they are tolerant on multiple invocation. If the when/latch/catch programmer forgot to think about this case, it would give the programmer of the observed object the opportunity to cause confusion in the observer's state. Casting it in principle-of-least-authority terms, we presume the whenResolved sender is only interested in allowing the recipient to invoke the observer once, so he should only provide him that authority and no more.

Syntactic sugar should capture safe idioms. After all, if the E programmer wants more flexibility, they can still use whenResolved manually. The proposed new expansion is:

     define temp2 := true
     r <- whenResolved(define done {
         to run(temp1) : void {
             if (temp2) {
                 temp2 := false
                 if (E isBroken(temp1)) {
                     define problem := E optProblem(temp1)
                     bad
                 } else {
                     define foo := temp1
                     good
                 }
             }
         }

})

Although this is formally a non-upwards compatible change, I suspect it is upwards compatible from all existing code. Does anyone see any problem with this?

MarcS, since you're currently the only when/latch/catch user I know, I'm especially eager for your reaction.

         Cheers,
         --MarkM