2016-02-18 17:49:56 +00:00
|
|
|
|
2017-05-01 12:54:41 +00:00
|
|
|
class(#pointer,#final,#limited) Process(Object)
|
2015-10-15 14:40:08 +00:00
|
|
|
{
|
2017-07-24 13:25:25 +00:00
|
|
|
var(#get) initialContext, currentContext, id, state.
|
2017-09-25 15:16:19 +00:00
|
|
|
var sp.
|
|
|
|
var(#get) ps_prev, ps_next, sem_wait_prev, sem_wait_next.
|
2017-07-24 13:25:25 +00:00
|
|
|
var sem, perr, perrmsg.
|
2015-10-15 14:40:08 +00:00
|
|
|
|
2018-05-15 16:38:37 +00:00
|
|
|
var asyncsg.
|
2019-09-09 07:43:14 +00:00
|
|
|
|
2017-04-25 15:20:58 +00:00
|
|
|
method primError { ^self.perr }
|
2017-05-16 02:04:18 +00:00
|
|
|
method primErrorMessage { ^self.perrmsg }
|
2017-09-25 15:16:19 +00:00
|
|
|
method(#primitive) sp.
|
|
|
|
|
2017-05-16 02:04:18 +00:00
|
|
|
method(#primitive) resume.
|
|
|
|
method(#primitive) yield.
|
2017-09-25 15:16:19 +00:00
|
|
|
method(#primitive) suspend.
|
2017-05-16 02:04:18 +00:00
|
|
|
method(#primitive) _terminate.
|
2016-07-04 15:36:10 +00:00
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method terminate
|
2016-07-01 16:31:47 +00:00
|
|
|
{
|
2019-06-27 06:29:09 +00:00
|
|
|
// search from the top context of the process down to intial_context and find ensure blocks and execute them.
|
|
|
|
// 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 := [
|
|
|
|
// [ thisProcess terminate. ] ensure: [System logNl: 'ensured....']
|
|
|
|
// ] newProcess.
|
|
|
|
// p resume.
|
|
|
|
// p terminate.
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
|
|
// the process must be frozen first. while unwinding is performed,
|
|
|
|
// the process must not be scheduled.
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-08-18 17:46:40 +00:00
|
|
|
// if the current active process(thisProcess) is not the process to terminate(self),
|
|
|
|
// suspend the target process so that no scheduling wakes the process until this
|
|
|
|
// termination is completed.
|
2019-06-27 06:29:09 +00:00
|
|
|
//if (Processor activeProcess ~~ self) { self suspend }.
|
2017-09-25 15:16:19 +00:00
|
|
|
if (thisProcess ~~ self) { self suspend }.
|
2019-08-18 17:46:40 +00:00
|
|
|
|
|
|
|
// TODO: what if there is another process that may resume this suspended process.
|
|
|
|
// should i mark it unresumable?
|
|
|
|
|
2017-07-24 13:25:25 +00:00
|
|
|
self.currentContext unwindTo: self.initialContext return: nil.
|
2016-07-01 16:31:47 +00:00
|
|
|
^self _terminate
|
|
|
|
}
|
2018-05-15 16:38:37 +00:00
|
|
|
|
|
|
|
method initAsync
|
|
|
|
{
|
|
|
|
if (self.asyncsg isNil) { self.asyncsg := SemaphoreGroup new }.
|
|
|
|
}
|
|
|
|
|
|
|
|
method addAsyncSemaphore: sem
|
|
|
|
{
|
|
|
|
^self.asyncsg addSemaphore: sem
|
|
|
|
}
|
|
|
|
|
|
|
|
method removeAsyncSemaphore: sem
|
|
|
|
{
|
|
|
|
^self.asyncsg removeSemaphore: sem
|
|
|
|
}
|
|
|
|
|
|
|
|
method handleAsyncEvent
|
|
|
|
{
|
|
|
|
^self.asyncsg wait.
|
|
|
|
}
|
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-09-21 07:56:51 +00:00
|
|
|
var waiting_head := nil,
|
2018-05-16 16:24:43 +00:00
|
|
|
waiting_tail := nil.
|
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
var count := 0. // semaphore signal count
|
2017-10-30 01:11:18 +00:00
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
var subtype := nil. // nil, io, timed
|
2018-05-17 10:21:22 +00:00
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
var heapIndex := nil, // overlaps as ioIndex
|
|
|
|
fireTimeSec := nil, // overlaps as ioHandle
|
|
|
|
fireTimeNsec := nil. // overlaps as ioType
|
2017-09-21 14:22:36 +00:00
|
|
|
|
2017-10-08 15:40:32 +00:00
|
|
|
var(#get,#set) signalAction := nil.
|
|
|
|
|
|
|
|
var(#get,#set) _group := nil,
|
|
|
|
_grm_next := nil,
|
|
|
|
_grm_prev := nil.
|
2016-02-18 17:49:56 +00:00
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// ==================================================================
|
2016-03-24 14:58:47 +00:00
|
|
|
|
2017-04-01 04:58:02 +00:00
|
|
|
method(#primitive) signal.
|
2017-10-05 17:14:38 +00:00
|
|
|
method(#primitive) _wait.
|
|
|
|
|
|
|
|
method wait
|
|
|
|
{
|
|
|
|
| k |
|
|
|
|
k := self _wait.
|
|
|
|
if (self.signalAction notNil) { self.signalAction value: self }.
|
|
|
|
^k
|
|
|
|
}
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// ==================================================================
|
2016-03-24 14:58:47 +00:00
|
|
|
|
2018-05-18 08:10:16 +00:00
|
|
|
method(#primitive) signalAfterSecs: secs.
|
|
|
|
method(#primitive) signalAfterSecs: secs nanosecs: nanosecs.
|
|
|
|
method(#primitive) signalOnInput: io_handle.
|
|
|
|
method(#primitive) signalOnOutput: io_handle.
|
|
|
|
method(#primitive) signalOnGCFin.
|
|
|
|
method(#primitive) unsignal.
|
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// ==================================================================
|
2018-05-18 08:10:16 +00:00
|
|
|
|
2018-05-17 10:21:22 +00:00
|
|
|
method heapIndex: index
|
|
|
|
{
|
|
|
|
self.heapIndex := index.
|
|
|
|
}
|
|
|
|
method headpIndex
|
|
|
|
{
|
|
|
|
^self.heapIndex.
|
|
|
|
}
|
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// ------------------------------------------
|
|
|
|
// TODO: either put fireTimeNsec into implementation of fireTime, and related methods.
|
|
|
|
// ------------------------------------------
|
2017-01-06 09:53:40 +00:00
|
|
|
method fireTime
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2018-05-16 16:24:43 +00:00
|
|
|
^self.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-07-21 16:54:43 +00:00
|
|
|
|
|
|
|
method notYoungerThan: aSemaphore
|
|
|
|
{
|
|
|
|
^self.fireTimeSec >= (aSemaphore fireTime)
|
|
|
|
}
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
2017-09-21 07:56:51 +00:00
|
|
|
|
2017-09-29 15:03:54 +00:00
|
|
|
class Mutex(Semaphore)
|
|
|
|
{
|
|
|
|
method(#class) new
|
|
|
|
{
|
|
|
|
| s |
|
|
|
|
s := super new.
|
|
|
|
s signal.
|
|
|
|
^s.
|
|
|
|
}
|
|
|
|
|
2019-06-19 12:38:09 +00:00
|
|
|
/*
|
2017-10-02 01:22:49 +00:00
|
|
|
TODO: how to prohibit wait and signal???
|
|
|
|
method(#prohibited) wait.
|
|
|
|
method(#prohibited) signal.
|
2019-06-19 12:38:09 +00:00
|
|
|
*/
|
2017-10-02 01:22:49 +00:00
|
|
|
|
|
|
|
method lock { ^super wait }
|
|
|
|
method unlock { ^super signal }
|
2017-09-29 15:03:54 +00:00
|
|
|
|
|
|
|
method critical: block
|
|
|
|
{
|
|
|
|
self wait.
|
|
|
|
^block ensure: [ self signal ]
|
|
|
|
}
|
|
|
|
}
|
2017-09-21 07:56:51 +00:00
|
|
|
|
|
|
|
|
2017-08-22 13:45:37 +00:00
|
|
|
class SemaphoreGroup(Object)
|
|
|
|
{
|
2019-06-27 06:29:09 +00:00
|
|
|
// the first two variables must match those of Semaphore.
|
2017-09-21 07:56:51 +00:00
|
|
|
var waiting_head := nil,
|
2018-05-17 10:21:22 +00:00
|
|
|
waiting_tail := nil.
|
2018-05-16 16:24:43 +00:00
|
|
|
|
|
|
|
var first_sem := nil,
|
2017-10-08 15:40:32 +00:00
|
|
|
last_sem := nil,
|
|
|
|
first_sigsem := nil,
|
2017-10-31 07:13:22 +00:00
|
|
|
last_sigsem := nil,
|
2018-04-15 16:24:31 +00:00
|
|
|
sem_io_count := 0,
|
|
|
|
sem_count := 0.
|
2017-08-22 13:45:37 +00:00
|
|
|
|
2019-06-19 12:38:09 +00:00
|
|
|
/* TODO: good idea to a shortcut way to prohibit a certain method in the heirarchy chain?
|
2017-08-22 13:45:37 +00:00
|
|
|
method(#class,#prohibited) new.
|
|
|
|
method(#class,#prohibited) new: size.
|
|
|
|
method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibility: #xxxx }
|
2019-06-19 12:38:09 +00:00
|
|
|
*/
|
2017-08-22 13:45:37 +00:00
|
|
|
|
2019-06-19 12:38:09 +00:00
|
|
|
/*
|
2017-08-22 13:45:37 +00:00
|
|
|
method(#class) new { self messageProhibited: #new }
|
|
|
|
method(#class) new: size { self messageProhibited: #new: }
|
2019-06-19 12:38:09 +00:00
|
|
|
*/
|
2017-08-22 13:45:37 +00:00
|
|
|
|
2017-11-24 17:40:20 +00:00
|
|
|
method(#primitive) addSemaphore: sem.
|
|
|
|
method(#primitive) removeSemaphore: sem.
|
2017-10-05 17:14:38 +00:00
|
|
|
method(#primitive) _wait.
|
|
|
|
|
|
|
|
method wait
|
|
|
|
{
|
2017-10-31 07:13:22 +00:00
|
|
|
| x |
|
|
|
|
x := self _wait.
|
2018-04-13 10:14:12 +00:00
|
|
|
if (x notError)
|
|
|
|
{
|
2019-06-27 06:29:09 +00:00
|
|
|
// TODO: is it better to check if x is an instance of Semaphore/SemaphoreGroup?
|
2018-04-13 10:14:12 +00:00
|
|
|
if (x signalAction notNil) { x signalAction value: x }.
|
|
|
|
}.
|
2017-10-31 07:13:22 +00:00
|
|
|
^x
|
2017-10-05 17:14:38 +00:00
|
|
|
}
|
2017-09-26 09:01:42 +00:00
|
|
|
|
|
|
|
method waitWithTimeout: seconds
|
|
|
|
{
|
|
|
|
| s r |
|
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// create an internal semaphore for timeout notification.
|
2017-09-26 09:01:42 +00:00
|
|
|
s := Semaphore new.
|
2017-10-31 07:13:22 +00:00
|
|
|
self addSemaphore: s.
|
2017-09-26 09:01:42 +00:00
|
|
|
|
2017-12-16 05:21:38 +00:00
|
|
|
[
|
2019-06-27 06:29:09 +00:00
|
|
|
// arrange the processor to notify upon timeout.
|
2018-05-18 08:10:16 +00:00
|
|
|
s signalAfterSecs: seconds.
|
2017-12-16 16:14:23 +00:00
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// wait on the semaphore group.
|
2017-12-16 05:21:38 +00:00
|
|
|
r := self wait.
|
2017-09-26 09:01:42 +00:00
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// if the internal semaphore has been signaled,
|
|
|
|
// arrange to return nil to indicate timeout.
|
|
|
|
if (r == s) { r := nil } // timed out
|
2019-07-26 04:40:33 +00:00
|
|
|
elif (r signalAction notNil) { r signalAction value: r }. // run the signal action block
|
2017-12-16 05:21:38 +00:00
|
|
|
] ensure: [
|
2019-06-27 06:29:09 +00:00
|
|
|
// System<<unsignal: doesn't thrown an exception even if the semaphore s is not
|
|
|
|
// register with System<<signal:afterXXX:. otherwise, i would do like this line
|
|
|
|
// commented out.
|
|
|
|
// [ s unsignal ] ensure: [ self removeSemaphore: s ].
|
2017-09-26 09:01:42 +00:00
|
|
|
|
2018-05-18 08:10:16 +00:00
|
|
|
s unsignal.
|
2017-12-16 16:14:23 +00:00
|
|
|
self removeSemaphore: s
|
2017-12-16 05:21:38 +00:00
|
|
|
].
|
2017-09-26 09:01:42 +00:00
|
|
|
|
|
|
|
^r.
|
|
|
|
}
|
2017-08-22 13:45:37 +00:00
|
|
|
}
|
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
|
|
|
{
|
2017-08-22 13:45:37 +00:00
|
|
|
| index newarr newsize |
|
2016-03-16 14:05:34 +00:00
|
|
|
|
|
|
|
index := self.size.
|
2017-08-22 13:45:37 +00:00
|
|
|
if (index >= (self.arr size))
|
|
|
|
{
|
2016-03-16 02:27:18 +00:00
|
|
|
newsize := (self.arr size) * 2.
|
|
|
|
newarr := Array new: newsize.
|
|
|
|
newarr copy: self.arr.
|
|
|
|
self.arr := newarr.
|
2017-08-22 13:45:37 +00:00
|
|
|
}.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
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.
|
2019-09-14 02:21:59 +00:00
|
|
|
self removeAt: 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.
|
2018-05-17 10:21:22 +00:00
|
|
|
item heapIndex: nil.
|
2016-03-22 14:18:07 +00:00
|
|
|
|
|
|
|
self.arr at: anIndex put: aSemaphore.
|
|
|
|
aSemaphore heapIndex: anIndex.
|
|
|
|
|
2017-07-21 16:54:43 +00:00
|
|
|
^if (aSemaphore youngerThan: item) { self siftUp: anIndex } else { self siftDown: anIndex }.
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2019-09-14 02:21:59 +00:00
|
|
|
method removeAt: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2017-07-21 16:54:43 +00:00
|
|
|
| item xitem |
|
2016-03-16 02:27:18 +00:00
|
|
|
|
|
|
|
item := self.arr at: anIndex.
|
2018-05-17 10:21:22 +00:00
|
|
|
item heapIndex: nil.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2016-03-16 14:05:34 +00:00
|
|
|
self.size := self.size - 1.
|
2017-07-21 16:54:43 +00:00
|
|
|
if (anIndex == self.size)
|
|
|
|
{
|
2019-06-27 06:29:09 +00:00
|
|
|
// the last item
|
2017-07-21 16:54:43 +00:00
|
|
|
self.arr at: self.size put: nil.
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xitem := self.arr at: self.size.
|
|
|
|
self.arr at: anIndex put: xitem.
|
|
|
|
xitem heapIndex: anIndex.
|
|
|
|
self.arr at: self.size put: nil.
|
|
|
|
if (xitem youngerThan: item) { self siftUp: anIndex } else { self siftDown: anIndex }.
|
|
|
|
}
|
2016-03-16 02:27:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 09:53:40 +00:00
|
|
|
method parentIndex: anIndex
|
2016-03-16 02:27:18 +00:00
|
|
|
{
|
2018-05-24 10:10:52 +00:00
|
|
|
^(anIndex - 1) div: 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
|
|
|
{
|
2017-07-21 16:54:43 +00:00
|
|
|
| pindex cindex par item |
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2017-07-21 16:54:43 +00:00
|
|
|
if (anIndex <= 0) { ^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
|
|
|
|
2017-07-21 16:54:43 +00:00
|
|
|
while (true)
|
|
|
|
{
|
2016-03-16 02:27:18 +00:00
|
|
|
cindex := pindex.
|
|
|
|
|
2017-07-21 16:54:43 +00:00
|
|
|
if (pindex <= 0) { break }.
|
|
|
|
|
|
|
|
pindex := self parentIndex: cindex.
|
|
|
|
par := self.arr at: pindex.
|
|
|
|
|
|
|
|
if (item notYoungerThan: par) { break }.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// item is younger than the parent.
|
|
|
|
// move the parent down
|
2017-07-21 16:54:43 +00:00
|
|
|
self.arr at: cindex put: par.
|
|
|
|
par heapIndex: cindex.
|
|
|
|
}.
|
|
|
|
|
2019-06-27 06:29:09 +00:00
|
|
|
// place the item as high as it can
|
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
|
|
|
{
|
2017-07-21 16:54:43 +00:00
|
|
|
| base capa cindex item
|
|
|
|
left right younger xitem |
|
2016-03-16 02:27:18 +00:00
|
|
|
|
2018-05-24 10:10:52 +00:00
|
|
|
base := self.size div: 2.
|
2017-07-21 16:54:43 +00:00
|
|
|
if (anIndex >= base) { ^anIndex }.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
|
|
|
cindex := anIndex.
|
|
|
|
item := self.arr at: cindex.
|
|
|
|
|
2017-07-21 16:54:43 +00:00
|
|
|
while (cindex < base)
|
|
|
|
{
|
2016-03-16 02:27:18 +00:00
|
|
|
left := self leftChildIndex: cindex.
|
|
|
|
right := self rightChildIndex: cindex.
|
|
|
|
|
2018-05-30 15:32:09 +00:00
|
|
|
younger := if ((right < self.size) and ((self.arr at: right) youngerThan: (self.arr at: left))) { right } else { left }.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
|
|
|
xitem := self.arr at: younger.
|
2017-07-21 16:54:43 +00:00
|
|
|
if (item youngerThan: xitem) { break }.
|
|
|
|
|
|
|
|
self.arr at: cindex put: xitem.
|
|
|
|
xitem heapIndex: cindex.
|
|
|
|
cindex := younger.
|
|
|
|
}.
|
2016-03-16 02:27:18 +00:00
|
|
|
|
|
|
|
self.arr at: cindex put: item.
|
|
|
|
item heapIndex: cindex.
|
|
|
|
|
|
|
|
^cindex
|
|
|
|
}
|
2016-02-18 17:49:56 +00:00
|
|
|
}
|
|
|
|
|
2017-05-01 12:54:41 +00:00
|
|
|
class(#final,#limited) ProcessScheduler(Object)
|
2015-10-15 14:40:08 +00:00
|
|
|
{
|
2019-08-26 14:43:41 +00:00
|
|
|
var(#get) active, total_count := 0.
|
2017-07-25 15:26:04 +00:00
|
|
|
var(#get) runnable_count := 0.
|
2017-07-24 13:25:25 +00:00
|
|
|
var runnable_head, runnable_tail.
|
2017-07-25 15:26:04 +00:00
|
|
|
var(#get) suspended_count := 0.
|
2017-07-24 13:25:25 +00:00
|
|
|
var suspended_head, suspended_tail.
|
2015-10-15 14:40:08 +00:00
|
|
|
|
2017-12-31 16:46:52 +00:00
|
|
|
method activeProcess { ^self.active }
|
2019-09-09 07:43:14 +00:00
|
|
|
method resume: proc { ^proc resume }
|
2015-10-15 14:40:08 +00:00
|
|
|
}
|