--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Monitor.st Fri May 03 17:33:31 1996 +0200
@@ -0,0 +1,189 @@
+"
+ COPYRIGHT (c) 1996 by Claus Gittinger
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+
+
+Object subclass:#Monitor
+ instanceVariableNames:'owningProcess sema count'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Kernel-Processes'
+!
+
+!Monitor class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1996 by Claus Gittinger
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+
+!
+
+documentation
+"
+ Monitors - functionality much like RecursionLocks, but not
+ block based.
+ Monitors are not unwind-save (i.e. a return or unwind while a
+ monitor is locked, will lead to a deadlock situation).
+ You have to care for unwinds yourself.
+
+ Notice:
+ This is an experimental demo class - there is no WARRANTY.
+ Smalltalkers should use Semaphores and RecursionLocks, which
+ are unwind-save.
+
+ [see also:]
+ RecursionLock Semaphore Delay SharedQueue
+ Block
+
+ [author:]
+ Claus Gittinger
+"
+
+!
+
+examples
+"
+ |mon p1 p2 p3|
+
+ mon := Monitor new.
+
+ p1 := [
+ 10 timesRepeat:[
+ Delay waitForSeconds:0.3.
+ mon enter.
+ 'p1 got it' printNL.
+ Delay waitForSeconds:0.3.
+ 'p1 leaves' printNL.
+ mon exit
+ ]
+ ] fork.
+
+ p2 := [
+ 20 timesRepeat:[
+ Delay waitForSeconds:0.2.
+ mon enter.
+ 'p2 got it' printNL.
+ Delay waitForSeconds:0.2.
+ 'p2 leaves' printNL.
+ mon exit
+ ]
+ ] fork.
+
+ p3 := [
+ 30 timesRepeat:[
+ Delay waitForSeconds:0.1.
+ mon enter.
+ 'p3 got it' printNL.
+ Delay waitForSeconds:0.1.
+ 'p3 leaves' printNL.
+ mon exit
+ ]
+ ] fork.
+
+
+"
+! !
+
+!Monitor class methodsFor:'instance creation'!
+
+new
+ ^ self basicNew initialize
+! !
+
+!Monitor methodsFor:'enter & leave'!
+
+enter
+ "enter the monitor"
+
+ |thisProcess wasBlocked|
+
+ thisProcess := Processor activeProcess.
+
+ "
+ this works only since interrupts are only serviced at
+ message send and method-return time ....
+ If you add a message send into the ifTrue:-block, things will
+ go mad ... (especially be careful when adding a debugPrint-here)
+ "
+ owningProcess isNil ifTrue:[
+ count := 1.
+ owningProcess := thisProcess.
+ ^ self
+ ].
+
+ owningProcess == thisProcess ifTrue:[
+ count := count + 1.
+ ^ self
+ ].
+
+ wasBlocked := OperatingSystem blockInterrupts.
+ [
+ [owningProcess notNil] whileTrue:[
+ sema wait.
+ ].
+ count := 1.
+ owningProcess := thisProcess.
+ ] valueOnUnwindDo:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts]
+ ]
+
+ "Modified: 3.5.1996 / 17:27:50 / cg"
+!
+
+exit
+ "exit the monitor"
+
+ |thisProcess|
+
+ thisProcess := Processor activeProcess.
+
+ "
+ this works only since interrupts are only serviced at
+ message send and method-return time ....
+ If you add a message send into the ifTrue:-block, things will
+ go mad ... (especially be careful when adding a debugPrint-here)
+ "
+ owningProcess ~~ thisProcess ifTrue:[
+ self halt:'invalid exit'
+ ].
+
+ count := count - 1.
+ count ~~ 0 ifTrue:[ ^ self].
+
+ owningProcess := nil.
+ sema signal.
+
+ "Modified: 3.5.1996 / 17:25:57 / cg"
+! !
+
+!Monitor methodsFor:'initialization'!
+
+initialize
+ sema := Semaphore new.
+ count := 0.
+
+ "Created: 3.5.1996 / 17:24:59 / cg"
+! !
+
+!Monitor class methodsFor:'documentation'!
+
+version
+ ^ '$Header: /cvs/stx/stx/libbasic2/Monitor.st,v 1.1 1996-05-03 15:33:31 cg Exp $'
+! !