[squeak-dev] Interaction between objects which can be waited on, and their clients(waiters)

Igor Stasenko siguctua at gmail.com
Tue May 5 15:10:40 UTC 2009


Hello list,

I stared @ DelayWaitTimeout class, and thinking, how to implement it
in new scheduler..
First i thought , just make it quickly and forget about it, but one
thing which don't makes me feel good about it, that
DelayWaitTimeout is a perfect example, when you need to stop a Process
until one of the multiple events occurs - in case of DelayWaitTimeout
its either semaphore signaled or delay expired.

So, i thinking, what if instead of implementing a DelayWaitTimeout ,
which works only for 2 objects - delay & semaphore, implement a more
generic class , which would allow us to wait for any number of objects
and blocks process until one of them is signaled. Or, blocks process
until all of them signaled.
There's nothing new, in fact, in Windoze there an API function, called
WaitForMultipleObjects, which does exactly what i describing - it
could wait on multiple objects, releasing a waiter once a single
object signaled, or release waiter only after all objects signaled.

Here is my thoughts, how to implement that.
First, we need to allow Delay & Semaphore to work with abstract waiter
object (not just Process).
A proposed protocol between object which acts as one who can be waited
on, and object who acts as waiter is following:

To start waiting, we sending a #waitForSignalBy: waiter
semaphore waitForSignalBy: waiter
or
delay waitForSignalBy: waiter

then, default #wait could be implemented, in both cases, simply as:

^ self waitForSignalBy: Processor activeProcess.

now, after issuing #waitForSignalBy: we have the following possible cases:
- given object is already signaled (as a semaphore with excess
signals), in this case we immediately sending #waitComplete: to waiter

- given object is scheduled for being signaled later , in this case we
sending #startWaitingOn: to waiter.

- now after #startWaitingOn: issued and once a semaphore/delay
signaled we sending #waitComplete: to waiter.

- in case if semaphore/delay abandoned, we sending #waitAbandoned: to
waiter. This happens, for instance, when we terminating a process who
currently waits on semaphore.

(If you have a better idea how to name these messages, please make a guess)

Now, by having such protocol implemented for Delay, Semaphore &
Process, we now can easily introduce another class which could allow
us to wait for multiple events.

Again, i'm not sure how properly call it..
Just want to illustrate the usage:

semaphore := Semaphore new.
delay := Delay forMilliseconds: 100.

signaler := (MultipleWait on: { semaphore. delay }) waitForOne.  "wait
until one of the listed objects get signaled"
or:
result := (MultipleWait on: { semaphore. delay }) waitForAll. "wait
until all of the listed objects get signaled"

by default, MultipleWait>>waitForSignalBy: is releasing waiter once
one of the listed objects signaled (as in waitForOne case).
Not sure about return result of #waitForAll, IMO , it could be just a
boolean value - return true, if all objects signaled, or false in case
if waiting abandoned.

Now, of course, since  MultipleWait acts as a waiter and as an object
who can be waited on, we can allow nesting:

mwait1 := MultipleWait on: { sema1. sema2 }.
(MultipleWait on: { mwait1. delay }) waitForOne.

and finally, as you may guess , a Semaphore>>waitTimeoutMSecs: now can
be implemented as:

waitTimeoutMSecs: anInteger
	"Wait on this semaphore for up to the given number of milliseconds,
then timeout.
	Return true if the deadline expired, false otherwise."
	| delay |

       delay := Delay forMilliseconds: (anInteger max: 0).
       ^ delay == (MultipleWait on: { self. delay }) waitForOne.


-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list