BoltLock.st
author Claus Gittinger <cg@exept.de>
Mon, 06 Aug 2012 16:32:26 +0200
changeset 2799 25cf016d4eed
parent 2798 ebd1bab6255e
child 2801 c1ed819bc4a9
permissions -rw-r--r--
class definition
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2798
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     1
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     2
 COPYRIGHT (c) 2012 by Claus Gittinger
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     3
              All Rights Reserved
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     4
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     5
 This software is furnished under a license and may be used
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     6
 only in accordance with the terms of that license and with the
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     7
 inclusion of the above copyright notice.   This software may not
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     8
 be provided or otherwise made available to, or used by, any
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     9
 other person.  No title to or ownership of the software is
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    10
 hereby transferred.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    11
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    12
"{ Package: 'stx:libbasic2' }"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    13
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    14
Object subclass:#BoltLock
2799
25cf016d4eed class definition
Claus Gittinger <cg@exept.de>
parents: 2798
diff changeset
    15
	instanceVariableNames:'state numReaders waitingProcesses name'
2798
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    16
	classVariableNames:'StateFree StateLocked StateBusy'
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    17
	poolDictionaries:''
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    18
	category:'Kernel-Processes'
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    19
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    20
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    21
!BoltLock class methodsFor:'documentation'!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    22
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    23
copyright
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    24
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    25
 COPYRIGHT (c) 2012 by Claus Gittinger
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    26
              All Rights Reserved
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    27
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    28
 This software is furnished under a license and may be used
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    29
 only in accordance with the terms of that license and with the
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    30
 inclusion of the above copyright notice.   This software may not
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    31
 be provided or otherwise made available to, or used by, any
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    32
 other person.  No title to or ownership of the software is
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    33
 hereby transferred.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    34
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    35
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    36
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    37
documentation
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    38
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    39
    A BoltLock (aka BoldVariable) is a 3-state semaphore, 
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    40
    useful to protect a resource against single writers, while allowing multiple
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    41
    readers to access the resource simultaneously.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    42
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    43
    The lock is in one of 3 states:
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    44
        A; free - can be changed by a writer into the locked state, or by a reader
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    45
                  into the busy state.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    46
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    47
        B; busy - can only be entered by another reader. left into free by last reader.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    48
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    49
        C; locked  - a single writer has the lock; no other reader or writer is allowed
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    50
                     to aquire it
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    51
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    52
    [caveat:]
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    53
        with many readers, the writers tend to make only very slow progress
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    54
        (need priority based wakeup).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    55
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    56
    [instance variables:]
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    57
        state                   <Symbol>
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    58
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    59
        numReaders              <Integer>               number of readers holding onto the lock
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    60
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    61
        waitingProcesses        <OrderedCollection>     waiting processes - will be served first
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    62
                                                        come first served when signalled.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    63
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    64
        name                    <String>                a debugging aid: an optional userFriendly
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    65
                                                        name; helps to identify a semaphore easier.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    66
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    67
    [see also:]
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    68
        Semaphore SemaphoreSet RecursionLock Monitor
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    69
        SharedQueue Delay 
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    70
        Process ProcessorScheduler
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    71
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    72
    [author:]
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    73
        Claus Gittinger
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    74
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    75
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    76
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    77
examples
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    78
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    79
    many processes synchronizing on a boltLock:
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    80
                                                        [exBegin]
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    81
        |lock readers readWriters|
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    82
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    83
        lock := BoltLock new.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    84
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    85
        readWriters := (1 to:10) collect:[:tNo |
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    86
                        [
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    87
                            10 timesRepeat:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    88
                                (Random nextIntegerBetween:1 and:6) == 1 ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    89
                                    Transcript showCR:('thread %1: want to write...' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    90
                                    lock waitForWrite.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    91
                                    Transcript showCR:('thread %1: **** write' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    92
                                    Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    93
                                    Transcript showCR:('thread %1: done writing.' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    94
                                    lock release.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    95
                                    Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    96
                                ] ifFalse:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    97
                                    Transcript showCR:('thread %1: want to read...' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    98
                                    lock waitForRead.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    99
                                    Transcript showCR:('thread %1: ---- read' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   100
                                    Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   101
                                    Transcript showCR:('thread %1: done reading.' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   102
                                    lock release.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   103
                                    Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   104
                                ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   105
                            ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   106
                            Transcript showCR:('thread %1: finished.').
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   107
                       ] newProcess name:('rw%1' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   108
                    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   109
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   110
        readers := (11 to:20) collect:[:tNo |
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   111
                        [
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   112
                            10 timesRepeat:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   113
                                Transcript showCR:('thread %1: want to read...' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   114
                                lock waitForRead.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   115
                                Transcript showCR:('thread %1: ---- read' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   116
                                Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   117
                                Transcript showCR:('thread %1: done.' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   118
                                lock release.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   119
                                Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   120
                            ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   121
                            Transcript showCR:('thread %1: finished.').
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   122
                       ] newProcess name:('r%1' bindWith:tNo).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   123
                    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   124
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   125
        readWriters do:[:t | t resume].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   126
        readers do:[:t | t resume].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   127
                                                        [exEnd]
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   128
"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   129
! !
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   130
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   131
!BoltLock class methodsFor:'instance creation'!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   132
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   133
new
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   134
    "return an initialized instance"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   135
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   136
    ^ self basicNew initialize.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   137
! !
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   138
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   139
!BoltLock class methodsFor:'class initialization'!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   140
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   141
initialize
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   142
    StateFree := #free.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   143
    StateBusy := #busy.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   144
    StateLocked := #locked.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   145
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   146
    "Created: / 06-08-2012 / 15:49:44 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   147
! !
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   148
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   149
!BoltLock methodsFor:'initialization'!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   150
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   151
initialize
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   152
    "Invoked when a new instance is created."
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   153
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   154
    state := StateFree.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   155
    numReaders := 0.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   156
    waitingProcesses := OrderedCollection new.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   157
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   158
    "Modified: / 06-08-2012 / 16:03:06 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   159
! !
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   160
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   161
!BoltLock methodsFor:'private'!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   162
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   163
addWaitingProcess:aProcess
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   164
    "add aProcess to the list of waiting processes.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   165
     all processes are ordered first-come-first-serve.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   166
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   167
     NOTE: must be called with blocked interrupts"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   168
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   169
    "for now"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   170
    waitingProcesses isNil ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   171
        waitingProcesses := Array with:aProcess
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   172
    ] ifFalse:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   173
        waitingProcesses isArray ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   174
            waitingProcesses := OrderedCollection withAll:waitingProcesses.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   175
        ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   176
        waitingProcesses add:aProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   177
    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   178
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   179
    "Created: / 06-08-2012 / 16:05:38 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   180
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   181
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   182
removeWaitingProcess:aProcess
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   183
    "remove aProcess from the list of waiting processes
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   184
     NO action if it is not in the list.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   185
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   186
     NOTE: must be called with blocked interrupts"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   187
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   188
    |nWaiting|
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   189
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   190
    nWaiting := waitingProcesses size.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   191
    nWaiting == 0 ifTrue:[^ self].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   192
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   193
    nWaiting == 1 ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   194
        (waitingProcesses at:1) == aProcess ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   195
            waitingProcesses := nil.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   196
        ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   197
        ^ self.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   198
    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   199
    waitingProcesses removeIdentical:aProcess ifAbsent:[].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   200
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   201
    "Created: / 06-08-2012 / 16:06:00 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   202
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   203
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   204
wakeupWaiters
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   205
    "remove all waiting processes from the list of waiting processes
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   206
     and resume them. 
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   207
     NOTE: Must be called when known that waitingProcesses is nonNil and
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   208
           also with blocked interrupts"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   209
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   210
    |processes|
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   211
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   212
    processes := waitingProcesses.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   213
    "/ do not set to nil - a waiting process may be suspended and will not be resumed...
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   214
    "/    waitingProcesses := nil.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   215
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   216
    "/ todo: resume by priority; higher first.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   217
    processes do:[:eachProcess | 
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   218
        Transcript showCR:('   wakeup thread %1' bindWith:eachProcess name).
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   219
        Processor resume:eachProcess
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   220
    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   221
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   222
    "Created: / 06-08-2012 / 16:05:01 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   223
! !
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   224
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   225
!BoltLock methodsFor:'waiting'!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   226
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   227
release
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   228
    "release the lock"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   229
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   230
    |activeProcess wasBlocked|
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   231
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   232
    wasBlocked := OperatingSystem blockInterrupts.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   233
    "/ Transcript showCR:'  release in state ',state.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   234
    activeProcess := Processor activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   235
    state == StateLocked ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   236
        "I am the writer"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   237
        state := StateFree.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   238
    ] ifFalse:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   239
        "I am a reader"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   240
        numReaders := numReaders - 1.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   241
        numReaders == 0 ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   242
            state := StateFree.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   243
        ]
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   244
    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   245
    state == StateFree ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   246
        waitingProcesses notEmptyOrNil ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   247
            self wakeupWaiters.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   248
        ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   249
    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   250
    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   251
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   252
    "Created: / 06-08-2012 / 16:00:04 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   253
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   254
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   255
waitForRead
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   256
    "wait for the lock in order to read"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   257
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   258
    |activeProcess wasBlocked|
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   259
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   260
    wasBlocked := OperatingSystem blockInterrupts.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   261
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   262
    "/ Transcript showCR:'  waitForRead in state ',state.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   263
    state == StateLocked ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   264
        "being written; wait until released"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   265
        activeProcess := Processor activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   266
        [
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   267
            self addWaitingProcess:activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   268
            [
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   269
                activeProcess suspendWithState:#waitForRead
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   270
            ] ifCurtailed:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   271
                "interrupts are not blocked when entered through Processor>>#interruptActive"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   272
                OperatingSystem blockInterrupts.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   273
                self removeWaitingProcess:activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   274
                wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   275
            ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   276
            self removeWaitingProcess:activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   277
        ] doUntil:[ state ~~ StateLocked].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   278
    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   279
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   280
    numReaders := numReaders + 1.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   281
    state := StateBusy.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   282
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   283
    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   284
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   285
    "Created: / 06-08-2012 / 15:49:08 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   286
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   287
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   288
waitForWrite
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   289
    "wait for the lock in order to read"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   290
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   291
    |activeProcess wasBlocked|
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   292
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   293
    wasBlocked := OperatingSystem blockInterrupts.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   294
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   295
    "/ Transcript showCR:'  waitForWrite in state ',state.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   296
    state ~~ StateFree ifTrue:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   297
        "being read or written"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   298
        activeProcess := Processor activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   299
        [
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   300
            self addWaitingProcess:activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   301
            [
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   302
                activeProcess suspendWithState:#waitForWrite
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   303
            ] ifCurtailed:[
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   304
                "interrupts are not blocked when entered through Processor>>#interruptActive"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   305
                OperatingSystem blockInterrupts.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   306
                self removeWaitingProcess:activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   307
                wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   308
            ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   309
            self removeWaitingProcess:activeProcess.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   310
        ] doUntil:[ state == StateFree].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   311
    ].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   312
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   313
    state := StateLocked.
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   314
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   315
    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   316
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   317
    "Created: / 06-08-2012 / 15:54:05 / cg"
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   318
! !
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   319
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   320
!BoltLock class methodsFor:'documentation'!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   321
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   322
version
2799
25cf016d4eed class definition
Claus Gittinger <cg@exept.de>
parents: 2798
diff changeset
   323
    ^ '$Header: /cvs/stx/stx/libbasic2/BoltLock.st,v 1.2 2012-08-06 14:32:26 cg Exp $'
2798
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   324
!
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   325
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   326
version_CVS
2799
25cf016d4eed class definition
Claus Gittinger <cg@exept.de>
parents: 2798
diff changeset
   327
    ^ '$Header: /cvs/stx/stx/libbasic2/BoltLock.st,v 1.2 2012-08-06 14:32:26 cg Exp $'
2798
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   328
! !
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   329
ebd1bab6255e initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   330
BoltLock initialize!