'From Squeak3.10.2 of ''5 June 2008'' [latest update: #7179] on 23 March 2009 at 8:13:53 pm'!
"Change Set:		AtomicProcessSuspend
Date:			23 March 2009
Author:			Andreas Raab

In-image support for atomic process suspend."!


!Process methodsFor: 'accessing' stamp: 'ar 12/7/2007 17:06'!
offList
	"OBSOLETE. Process>>suspend will atomically reset myList if the process is suspended. 
	There should never be a need to send #offList but some older users may not be aware 
	of the changed semantics to suspend and may try the old hickadidoo seen here:

		(suspendingList := process suspendingList) == nil
			ifTrue: [process == Processor activeProcess ifTrue: [process suspend]]
			ifFalse: [suspendingList remove: process ifAbsent:[].
					process offList].

	Usages like the above should be replaced by a simple 'process suspend' "
	myList := nil! !

!Process methodsFor: 'changing process state' stamp: 'ar 12/7/2007 17:10'!
suspend
	"Primitive. 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.
	The return value of this method is the list the receiver was previously on (if any)."
	| oldList |
	<primitive: 88>
	"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:[^nil]. "this allows us to use suspend multiple times"
	oldList := myList.
	myList := nil.
	oldList remove: self ifAbsent:[].
	^oldList! !

!Process methodsFor: 'changing process state' stamp: 'ar 3/23/2009 20:04'!
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 suspend.
	] ifFalse:[
		myList ifNotNil:[oldList := self suspend].
		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']].
	].
! !

Process removeSelector: #primitiveSuspend!
