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

Andreas Raab andreas.raab at gmx.de
Tue May 5 16:08:03 UTC 2009


Just for fun, find an attached a version of MultiWait that works just 
like described earlier. If you run the benchmarks on MultiWait you'll 
find that DelayWaitTimeout is about 5x faster when compared with the 
naive MultiWait equivalent.

Cheers,
   - Andreas

Andreas Raab wrote:
> Hi Igor -
> 
> How is what you are proposing fundamentally different from a solution 
> that simply creates a watcher process for each event source and then 
> combines those properly? I.e.,
> 
> Object subclass: #MultiWait
>   instanceVariableNames: 'eventSemas'
>   ...
> 
> waitForAll
>   "waits for signals from all event sources"
>   eventSemas do:[:sema| sema wait].
> 
> waitForOne
>   "Waits for signals from at least one event source.
>    Returns all the semaphores that have been signaled."
>   waitSema := Semaphore new.
>   processes := eventSemas do:[:sema| [sema wait. waitSema signal] fork].
>   waitSema wait. "or waitTimeoutMSecs:"
>   signaled := Set new.
>   eventSemas with: processes do:[:list :proc|
>     (proc suspend == list) ifTrue:[signaled add: list].
>     proc terminate.
>   ].
>   ^signaled
> 
> DelayWaitTimeout is an optimization that avoids the need for additional 
> processes - when you use #waitTimeoutMSecs: a *lot* (say, because you're 
> running a server with heavy network activity) the additional overhead 
> incurred by the additional processes (and process switches) gets 
> relevant in a hurry. But other than that, the above is a straightforward 
> solution that will work with anything that supports the #wait protocol.
> 
> Cheers,
>   - Andreas
> 
> Igor Stasenko wrote:
>> 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.
>>
>>
> 
> 
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: MultiWait.1.cs
Type: text/x-csharp
Size: 1939 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20090505/fa3bb733/MultiWait.1.bin


More information about the Squeak-dev mailing list