Monitor.st
changeset 272 32ebd03ddb58
child 273 c66a8556b40f
--- /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 $'
+! !