2016-02-18 17:49:56 +00:00
|
|
|
|
2017-04-30 04:50:33 +00:00
|
|
|
class(#pointer,#limited) Process(Object)
|
2015-10-15 14:40:08 +00:00
|
|
|
{
|
2017-04-25 15:20:58 +00:00
|
|
|
var initial_context, current_context, state, sp, prev, next, sem, perr.
|
2015-10-19 06:16:43 +00:00
|
|
|
|
2017-04-26 15:31:07 +00:00
|
|
|
method(#class) basicNew
|
2015-10-19 06:16:43 +00:00
|
|
|
{
|
2017-04-26 15:31:07 +00:00
|
|
|
(* instantiation is not allowed. a process is strictly a VM managed object *)
|
|
|
|
self cannotInstantiate
|
|
|
|
}
|
|
|
|
|
|
|
|
method(#class) basicNew: size
|
|
|
|
{
|
|
|
|
(* instantiation is not allowed. a process is strictly a VM managed object *)
|
|
|
|
self cannotInstantiate
|
2015-10-19 06:16:43 +00:00
|
|
|
}
|
2015-10-15 14:40:08 +00:00
|
|
|
|
2017-04-25 15:20:58 +00:00
|
|
|
method prev { ^self.prev }
|
|
|
|
method next { ^self.next }
|
2015-10-15 14:40:08 +00:00
|
|
|
|
2017-04-25 15:20:58 +00:00
|
|
|
method next: process { self.next := process }
|
|
|
|
method prev: process { self.prev := process }
|
2015-10-15 14:40:08 +00:00
|
|
|
|
2017-04-25 15:20:58 +00:00
|
|
|
method primError { ^self.perr }
|
2015-10-18 15:06:17 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method resume
|
2015-10-18 15:06:17 +00:00
|
|
|
{
|
2016-02-19 15:52:56 +00:00
|
|
|
<primitive: #_process_resume>
|
|
|
|
self primitiveFailed
|
|
|
|
|
|
|
|
##^Processor resume: self.
|
2015-10-18 15:06:17 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method _terminate
|
2016-02-14 06:35:18 +00:00
|
|
|
{
|
|
|
|
<primitive: #_process_terminate>
|
|
|
|
self primitiveFailed
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method _suspend
|
2016-07-04 15:36:10 +00:00
|
|
|
{
|
|
|
|
<primitive: #_process_suspend>
|
|
|
|
self primitiveFailed
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method terminate
|
2016-07-01 16:31:47 +00:00
|
|
|
{
|
|
|
|
##search from the top contextof the process down to intial_contextand find ensure blocks and execute them.
|
2016-07-04 15:36:10 +00:00
|
|
|
## if a different process calls 'terminate' on a process,
|
|
|
|
## the ensureblock is not executed in the context of the
|
|
|
|
## process being terminated, but in the context of terminatig process.
|
|
|
|
##
|
|
|
|
## 1) process termianted by another process
|
|
|
|
## p := [
|
|
|
|
## [ 1 to: 10000 by: 1 do: [:ex | System logNl: i asString] ] ensure: [System logNl: 'ensured....']
|
|
|
|
## ] newProcess.
|
|
|
|
## p resume.
|
|
|
|
## p terminate.
|
|
|
|
##
|
|
|
|
## 2) process terminated by itself
|
|
|
|
## p := [
|
2016-07-05 15:22:29 +00:00
|
|
|
## [ thisProcess terminate. ] ensure: [System logNl: 'ensured....']
|
2016-07-04 15:36:10 +00:00
|
|
|
## ] newProcess.
|
|
|
|
## p resume.
|
|
|
|
## p terminate.
|
|
|
|
## ----------------------------------------------------------------------------------------------------------
|
|
|
|
## the process must be frozen first. while unwinding is performed,
|
|
|
|
## the process must not be scheduled.
|
|
|
|
## ----------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-07-05 15:22:29 +00:00
|
|
|
##(Processor activeProcess ~~ self) ifTrue: [ self _suspend ].
|
|
|
|
(thisProcess ~~ self) ifTrue: [ self _suspend ].
|
2016-07-01 16:31:47 +00:00
|
|
|
self.current_context unwindTo: self.initial_context return: nil.
|
|
|
|
^self _terminate
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method yield
|
2016-02-19 15:52:56 +00:00
|
|
|
{
|
|
|
|
<primitive: #_process_yield>
|
|
|
|
self primitiveFailed
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method sp
|
2016-02-12 16:23:26 +00:00
|
|
|
{
|
2016-06-24 14:29:43 +00:00
|
|
|
^self.sp.
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method initialContext
|
2016-06-24 14:29:43 +00:00
|
|
|
{
|
|
|
|
^self.initial_context
|
2016-02-12 16:23:26 +00:00
|
|
|
}
|
2015-10-15 14:40:08 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
class Semaphore(Object)
|
2016-02-18 17:49:56 +00:00
|
|
|
{
|
2017-04-24 04:26:03 +00:00
|
|
|
var count := 0,
|
|
|
|
waiting_head := nil,
|
|
|
|
waiting_tail := nil,
|
|
|
|
heapIndex := -1,
|
|
|
|
fireTimeSec := 0,
|
|
|
|
fireTimeNsec := 0,
|
|
|
|
ioIndex := -1,
|
|
|
|
ioData := nil,
|
|
|
|
ioMask := 0.
|
2016-02-18 17:49:56 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method(#class) forMutualExclusion
|
2016-05-18 15:10:00 +00:00
|
|
|
{
|
|
|
|
| sem |
|
|
|
|
sem := self new.
|
|
|
|
sem signal.
|
|
|
|
^sem
|
|
|
|
}
|
|
|
|
|
2016-03-24 14:58:47 +00:00
|
|
|
## ==================================================================
|
|
|
|
|
2017-04-01 04:58:02 +00:00
|
|
|
method(#primitive) signal.
|
|
|
|
method(#primitive) wait.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2017-04-01 04:58:02 +00:00
|
|
|
(*
|
2017-01-06 09:53:40 +00:00
|
|
|
method waitWithTimeout: seconds
|
2016-03-24 14:58:47 +00:00
|
|
|
{
|
|
|
|
<primitive: #_semaphore_wait>
|
|
|
|
self primitiveFailed
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method waitWithTimeout: seconds and: nanoSeconds
|
2016-03-24 14:58:47 +00:00
|
|
|
{
|
|
|
|
<primitive: #_semaphore_wait>
|
|
|
|
self primitiveFailed
|
|
|
|
}
|
2017-04-01 04:58:02 +00:00
|
|
|
*)
|
2017-01-06 09:53:40 +00:00
|
|
|
method critical: aBlock
|
2016-05-17 15:12:27 +00:00
|
|
|
{
|
|
|
|
self wait.
|
|
|
|
^aBlock ensure: [ self signal ]
|
|
|
|
}
|
|
|
|
|
2016-03-24 14:58:47 +00:00
|
|
|
## ==================================================================
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method heapIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
|
|
|
^heapIndex
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method heapIndex: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
|
|
|
heapIndex := anIndex
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method fireTime
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-22 14:18:07 +00:00
|
|
|
^fireTimeSec
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method fireTime: anInteger
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-22 14:18:07 +00:00
|
|
|
self.fireTimeSec := anInteger.
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method youngerThan: aSemaphore
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-22 14:18:07 +00:00
|
|
|
^self.fireTimeSec < (aSemaphore fireTime)
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
class SemaphoreHeap(Object)
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2017-04-19 16:46:44 +00:00
|
|
|
var arr, size.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method initialize
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
|
|
|
self.size := 0.
|
|
|
|
self.arr := Array new: 100.
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method size
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
|
|
|
^self.size
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method at: anIndex
|
2016-03-16 10:13:03 +00:00
|
|
|
{
|
|
|
|
^self.arr at: anIndex.
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method insert: aSemaphore
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-16 14:05:34 +00:00
|
|
|
| index |
|
|
|
|
|
|
|
|
index := self.size.
|
|
|
|
(index >= (self.arr size)) ifTrue: [
|
2016-03-16 02:27:18 +00:00
|
|
|
| newarr newsize |
|
|
|
|
newsize := (self.arr size) * 2.
|
|
|
|
newarr := Array new: newsize.
|
|
|
|
newarr copy: self.arr.
|
|
|
|
self.arr := newarr.
|
|
|
|
].
|
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
self.arr at: index put: aSemaphore.
|
|
|
|
aSemaphore heapIndex: index.
|
2016-03-16 02:27:18 +00:00
|
|
|
self.size := self.size + 1.
|
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
^self siftUp: index
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method popTop
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
|
|
|
| top |
|
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
top := self.arr at: 0.
|
|
|
|
self deleteAt: 0.
|
2016-03-16 02:27:18 +00:00
|
|
|
^top
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method updateAt: anIndex with: aSemaphore
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-22 14:18:07 +00:00
|
|
|
| item |
|
|
|
|
|
|
|
|
item := self.arr at: anIndex.
|
|
|
|
item heapIndex: -1.
|
|
|
|
|
|
|
|
self.arr at: anIndex put: aSemaphore.
|
|
|
|
aSemaphore heapIndex: anIndex.
|
|
|
|
|
|
|
|
^(aSemaphore youngerThan: item)
|
|
|
|
ifTrue: [ self siftUp: anIndex ]
|
|
|
|
ifFalse: [ self siftDown: anIndex ].
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method deleteAt: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
|
|
|
| item |
|
|
|
|
|
|
|
|
item := self.arr at: anIndex.
|
|
|
|
item heapIndex: -1.
|
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
self.size := self.size - 1.
|
2016-03-16 02:27:18 +00:00
|
|
|
(anIndex == self.size)
|
|
|
|
ifTrue: [
|
|
|
|
"the last item"
|
|
|
|
self.arr at: self.size put: nil.
|
|
|
|
]
|
|
|
|
ifFalse: [
|
|
|
|
| xitem |
|
|
|
|
|
|
|
|
xitem := self.arr at: self.size.
|
|
|
|
self.arr at: anIndex put: xitem.
|
|
|
|
xitem heapIndex: anIndex.
|
|
|
|
self.arr at: self.size put: nil.
|
|
|
|
|
|
|
|
(xitem youngerThan: item)
|
|
|
|
ifTrue: [self siftUp: anIndex ]
|
|
|
|
ifFalse: [self siftDown: anIndex ]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method parentIndex: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-16 14:05:34 +00:00
|
|
|
^(anIndex - 1) quo: 2
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method leftChildIndex: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-16 14:05:34 +00:00
|
|
|
^(anIndex * 2) + 1.
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method rightChildIndex: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-16 14:05:34 +00:00
|
|
|
^(anIndex * 2) + 2.
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method siftUp: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-16 10:13:03 +00:00
|
|
|
| pindex cindex par item stop |
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
(anIndex <= 0) ifTrue: [ ^anIndex ].
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2016-03-16 10:13:03 +00:00
|
|
|
pindex := anIndex.
|
|
|
|
item := self.arr at: anIndex.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2016-03-16 10:13:03 +00:00
|
|
|
stop := false.
|
|
|
|
[ stop ] whileFalse: [
|
2016-03-16 02:27:18 +00:00
|
|
|
|
|
|
|
cindex := pindex.
|
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
(cindex > 0)
|
2016-03-16 10:13:03 +00:00
|
|
|
ifTrue: [
|
|
|
|
pindex := self parentIndex: cindex.
|
|
|
|
par := self.arr at: pindex.
|
|
|
|
|
|
|
|
(item youngerThan: par)
|
|
|
|
ifTrue: [
|
|
|
|
## move the parent down
|
|
|
|
self.arr at: cindex put: par.
|
|
|
|
par heapIndex: cindex.
|
|
|
|
]
|
|
|
|
ifFalse: [ stop := true ].
|
|
|
|
]
|
|
|
|
ifFalse: [ stop := true ].
|
2016-03-16 02:27:18 +00:00
|
|
|
].
|
|
|
|
|
2016-03-16 10:13:03 +00:00
|
|
|
self.arr at: cindex put: item.
|
|
|
|
item heapIndex: cindex.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
|
|
|
^cindex
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method siftDown: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
|
|
|
| base capa cindex item |
|
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
base := self.size quo: 2.
|
|
|
|
(anIndex >= base) ifTrue: [^anIndex].
|
2016-03-16 02:27:18 +00:00
|
|
|
|
|
|
|
cindex := anIndex.
|
|
|
|
item := self.arr at: cindex.
|
|
|
|
|
|
|
|
[ cindex < base ] whileTrue: [
|
|
|
|
| left right younger xitem |
|
|
|
|
|
|
|
|
left := self leftChildIndex: cindex.
|
|
|
|
right := self rightChildIndex: cindex.
|
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
((right < self.size) and: [(self.arr at: right) youngerThan: (self.arr at: left)])
|
2016-03-16 02:27:18 +00:00
|
|
|
ifTrue: [ younger := right ]
|
|
|
|
ifFalse: [ younger := left ].
|
|
|
|
|
|
|
|
xitem := self.arr at: younger.
|
|
|
|
(item youngerThan: xitem)
|
|
|
|
ifTrue: [
|
|
|
|
"break the loop"
|
|
|
|
base := anIndex
|
|
|
|
]
|
|
|
|
ifFalse: [
|
|
|
|
self.arr at: cindex put: xitem.
|
|
|
|
xitem heapIndex: cindex.
|
|
|
|
cindex := younger.
|
|
|
|
]
|
|
|
|
].
|
|
|
|
|
|
|
|
self.arr at: cindex put: item.
|
|
|
|
item heapIndex: cindex.
|
|
|
|
|
|
|
|
^cindex
|
|
|
|
}
|
2016-02-18 17:49:56 +00:00
|
|
|
}
|
|
|
|
|
2017-04-30 04:50:33 +00:00
|
|
|
class(#limited) ProcessScheduler(Object)
|
2015-10-15 14:40:08 +00:00
|
|
|
{
|
2017-04-19 16:46:44 +00:00
|
|
|
var tally, active, runnable_head, runnable_tail, sem_heap.
|
2015-10-15 14:40:08 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method new
|
2015-10-15 14:40:08 +00:00
|
|
|
{
|
|
|
|
"instantiation is not allowed"
|
|
|
|
^nil. "TODO: raise an exception"
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method activeProcess
|
2015-10-15 14:40:08 +00:00
|
|
|
{
|
|
|
|
^self.active.
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method resume: process
|
2015-10-22 02:47:25 +00:00
|
|
|
{
|
|
|
|
<primitive: #_processor_schedule>
|
|
|
|
self primitiveFailed.
|
2015-10-15 14:40:08 +00:00
|
|
|
|
2015-10-22 02:47:25 +00:00
|
|
|
"The primitive does something like the following in principle:
|
2015-10-15 14:40:08 +00:00
|
|
|
(self.tally = 0)
|
|
|
|
ifTrue: [
|
2016-06-24 14:29:43 +00:00
|
|
|
self.head := process.
|
|
|
|
self.tail := process.
|
2015-10-15 14:40:08 +00:00
|
|
|
self.tally := 1.
|
|
|
|
]
|
|
|
|
ifFalse: [
|
2016-06-24 14:29:43 +00:00
|
|
|
process next: self.head.
|
|
|
|
self.head prev: process.
|
|
|
|
self.head := process.
|
2015-10-15 14:40:08 +00:00
|
|
|
self.tally := self.tally + 1.
|
2015-10-22 02:47:25 +00:00
|
|
|
].
|
|
|
|
"
|
2015-10-18 15:06:17 +00:00
|
|
|
}
|
|
|
|
|
2015-10-15 14:40:08 +00:00
|
|
|
"
|
2017-01-06 09:53:40 +00:00
|
|
|
method yield
|
2015-10-15 14:40:08 +00:00
|
|
|
{
|
2015-10-22 02:47:25 +00:00
|
|
|
<primitive: #_processor_yield>
|
2015-10-15 14:40:08 +00:00
|
|
|
self primitiveFailed
|
|
|
|
}
|
|
|
|
"
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method signal: semaphore after: secs
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2016-03-22 14:18:07 +00:00
|
|
|
<primitive: #_processor_add_timed_semaphore>
|
|
|
|
self primitiveFailed.
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method signal: semaphore after: secs and: nanosecs
|
2016-03-22 14:18:07 +00:00
|
|
|
{
|
|
|
|
<primitive: #_processor_add_timed_semaphore>
|
|
|
|
self primitiveFailed.
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
2016-03-24 14:58:47 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method unsignal: semaphore
|
2016-03-24 14:58:47 +00:00
|
|
|
{
|
|
|
|
<primitive: #_processor_remove_semaphore>
|
|
|
|
self primitiveFailed.
|
|
|
|
}
|
|
|
|
|
2017-02-15 11:57:24 +00:00
|
|
|
method signal: semaphore onInput: file
|
2016-03-24 14:58:47 +00:00
|
|
|
{
|
2017-02-15 11:57:24 +00:00
|
|
|
<primitive: #_processor_add_input_semaphore>
|
|
|
|
self primitiveFailed.
|
|
|
|
}
|
|
|
|
method signal: semaphore onOutput: file
|
2016-03-24 14:58:47 +00:00
|
|
|
{
|
2017-02-15 11:57:24 +00:00
|
|
|
<primitive: #_processor_add_output_semaphore>
|
|
|
|
self primitiveFailed.
|
|
|
|
}
|
|
|
|
method signal: semaphore onInOutput: file
|
|
|
|
{
|
|
|
|
<primitive: #_processor_add_inoutput_semaphore>
|
|
|
|
self primitiveFailed.
|
|
|
|
}
|
2016-03-28 13:25:36 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method return: object to: context
|
2016-03-28 13:25:36 +00:00
|
|
|
{
|
|
|
|
<primitive: #_processor_return_to>
|
|
|
|
self primitiveFailed.
|
|
|
|
}
|
2016-07-01 16:31:47 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method sleepFor: secs
|
2016-07-01 16:31:47 +00:00
|
|
|
{
|
|
|
|
## -----------------------------------------------------
|
|
|
|
## put the calling process to sleep for given seconds.
|
|
|
|
## -----------------------------------------------------
|
|
|
|
| s |
|
|
|
|
s := Semaphore new.
|
|
|
|
self signal: s after: secs.
|
|
|
|
s wait.
|
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method sleepFor: secs and: nanosecs
|
2016-07-01 16:31:47 +00:00
|
|
|
{
|
|
|
|
## -----------------------------------------------------
|
|
|
|
## put the calling process to sleep for given seconds.
|
|
|
|
## -----------------------------------------------------
|
|
|
|
| s |
|
|
|
|
s := Semaphore new.
|
|
|
|
self signal: s after: secs and: nanosecs
|
|
|
|
s wait.
|
|
|
|
}
|
2015-10-15 14:40:08 +00:00
|
|
|
}
|