'From Croquet1.0beta of 11 April 2006 [latest update: #1] on 4 December 2007 at 4:33:43 pm'! !ControlManager methodsFor: 'scheduling' stamp: 'ar 12/4/2007 15:44'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller." | newActiveController | activeControllerProcess suspend. activeController ~~ nil ifTrue: [ "Carefully de-emphasis the current window." activeController view topView deEmphasizeForDebugger]. newActiveController := (ToolSet interrupt: activeControllerProcess label: labelString) controller. newActiveController centerCursorInView. self activeController: newActiveController. ! ! !Process methodsFor: 'changing process state' stamp: 'ar 12/4/2007 15:49'! primitiveSuspend "Primitive. Stop the process that self represents in such a way that it can be restarted at a later time (by sending #resume). If the receiver is not the active process it will take it off its suspendingList. Essential. See Object documentation whatIsAPrimitive." | oldList | "This is fallback code for VMs which only support the old primitiveSuspend which would not accept processes that are waiting to be run." myList ifNil:[self error: 'Process already suspended']. oldList := myList. myList := nil. oldList remove: self ifAbsent:[]. ^oldList! ! !Process methodsFor: 'changing process state' stamp: 'ar 12/4/2007 15:30'! suspend "Stop the process that the receiver represents in such a way that it can be restarted at a later time (by sending the receiver the message resume). If the receiver represents the activeProcess, suspend it. Otherwise remove the receiver from the list of waiting processes." self primitiveSuspend. ! ! !Process methodsFor: 'changing process state' stamp: 'ar 12/4/2007 15:55'! terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating." | ctxt unwindBlock oldList | self isActiveProcess ifTrue: [ ctxt := thisContext. [ ctxt := ctxt findNextUnwindContextUpTo: nil. ctxt isNil ] whileFalse: [ unwindBlock := ctxt tempAt: 1. unwindBlock ifNotNil: [ ctxt tempAt: 1 put: nil. thisContext terminateTo: ctxt. unwindBlock value]. ]. thisContext terminateTo: nil. self primitiveSuspend. ] ifFalse: [ self isSuspended ifFalse:[oldList := self primitiveSuspend]. suspendedContext ifNotNil: [ "Figure out if we are terminating the process while waiting in Semaphore>>critical: In this case, pop the suspendedContext so that we leave the ensure: block inside Semaphore>>critical: without signaling the semaphore." (oldList class == Semaphore and:[ suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[ suspendedContext := suspendedContext home. ]. ctxt := self popTo: suspendedContext bottomContext. ctxt == suspendedContext bottomContext ifFalse: [ self debug: ctxt title: 'Unwind error during termination']]. ]. ! ! !Project class methodsFor: 'utilities' stamp: 'ar 12/4/2007 15:47'! interruptName: labelString "Create a Notifier on the active scheduling process with the given label." | projectProcess | Smalltalk isMorphic ifFalse: [^ ScheduledControllers interruptName: labelString]. ActiveHand ifNotNil:[ActiveHand interrupted]. ActiveWorld := World. "reinstall active globals" ActiveHand := World primaryHand. ActiveHand interrupted. "make sure this one's interrupted too" ActiveEvent := nil. projectProcess := self uiProcess. "we still need the accessor for a while" projectProcess suspend. ToolSet interrupt: projectProcess label: labelString! ! Process removeSelector: #offList!