[e-cvs] cvs commit: e/src/esrc/org/erights/e/elang/cmd controlLoopMakerAuthor.emaker controlLoopMakerAuthor.updoc

markm@eros.cs.jhu.edu markm@eros.cs.jhu.edu
Wed, 15 Aug 2001 23:05:38 -0400


markm       01/08/15 23:05:37

  Added:       src/esrc/org/erights/e/elang/cmd
                        controlLoopMakerAuthor.emaker
                        controlLoopMakerAuthor.updoc
  Log:
  beginnings of command loop in E

Revision  Changes    Path
1.1                  e/src/esrc/org/erights/e/elang/cmd/controlLoopMakerAuthor.emaker

Index: controlLoopMakerAuthor.emaker
===================================================================
def controlLoopMakerAuthor(QueueMaker) :any {
    class controlLoopMaker() :any {
        var myShouldBlock := false
        var myIsAlarmSet := false
        # if non-null, we *should* exit
        var myOptExitPair := null
        # if non-null, we *have* exitted
        var myOptQueue := QueueMaker new()

        def internalLoop

        def setAlarm() {
            if (! myIsAlarmSet && ! myShouldBlock && myOptQueue != null) {
               myIsAlarmSet := true
               internalLoop <- ()
            }
        }

        def bind internalLoop() {
            myIsAlarmSet := false
            if (myShouldBlock) {
                # do nothing
            } else if (myOptExitPair != null) {
                myOptQueue := null
            } else if (myOptQueue optDequeue() =~ runnable ? (runnable != null)) {
                try {
                    runnable()
                } catch problem {
                    myOptExitPair := [-1, problem]
                }
                setAlarm()
            } else {
                # queue is empty, do nothing
            }
        }

        def controlLoop {
            to blockAtTop() {
                myShouldBlock := true
            }
            to continueAtTop() {
                myShouldBlock := false
                setAlarm()
            }
            to waitAtTop(ref) {
                Ref whenResolved(ref, def _(_){ 
                    controlLoop continueAtTop()
                })
            }
            to exitAtTop() {
                myOptExitPair := [0, null]
                setAlarm()
            }
            to exitAtTop(exitCode, optProblem) {
                myOptExitPair := [exitCode, optProblem]
                setAlarm()
            }
            to enqueue(runnable) {
                if (myOptQueue != null) {
                    myOptQueue enqueue(runnable)
                    setAlarm()
                }
            }
            # Returns a pair of an exit code and an optional problem.
            # Normally, an exit code of zero should have no problem
            # whereas any other exit code should have a problem, but
            # this is not enforced.  XXX It probably should be and 
            # will be enforced.
            to getOptExitPair() :any {
                if (myOptQueue == null) {
                    require(myOptExitPair != null,
                            thunk{"internal: no exit pair"})
                    myOptExitPair
                } else {
                    null
                }
            }
        }
    }
}




1.1                  e/src/esrc/org/erights/e/elang/cmd/controlLoopMakerAuthor.updoc

Index: controlLoopMakerAuthor.updoc
===================================================================
    ? def QueueMaker := <unsafe:org.erights.e.elib.prim.Queue>
    # value: <unsafe:org.erights.e.elib.prim.Queue>
    
    ? def controlLoopMaker := <import:org.erights.e.elang.cmd.controlLoopMakerAuthor>(QueueMaker)
    # value: <controlLoopMaker>
    
    ? def ctrl := controlLoopMaker new()
    # value: <controlLoop>
    
    ? ctrl enqueue(thunk{println("foo")})
    ? 
    foo
    ? (ctrl enqueue(thunk{println("bar")})
    >  ctrl blockAtTop()
    >  ctrl enqueue(thunk{println("baz")})
    > )
    ? 
    ? ctrl continueAtTop()
    ? 
    bar
    baz
    ? def [p,r] := PromiseMaker()
    # value: [<Eventual ref>, <Open Resolver>]
    
    ? def event() {
    >     println("before")
    >     ctrl blockAtTop()
    >     println("after")
    >     ctrl enqueue(thunk{println("next")})
    >     ctrl waitAtTop(p)
    > }
    # value: <event>
    
    ? ctrl enqueue(event)
    ? 
    before
    after
    ? 
    ? r resolve(3)
    ? 
    next
    ? ctrl getOptExitPair()
    ? def event2() {
    >     ctrl exitAtTop()
    >     println(`exit: ${ctrl getOptExitPair()}`)
    >     ctrl enqueue(thunk{println("already dead")})
    > }
    # value: <event2>
    
    ? ctrl enqueue(event2)
    ? 
    exit: null
    ? 
    ? ctrl getOptExitPair()
    # value: [0, null]
    
    ?