Tried to come up with a text for the documentation for the EventSemaphore class.

Please check the raildiagrams and descriptions for the methods.

Also please note that the example got simplified in the formatting somewhat 
(e.g. the date portion
is not used anymore, making the output better legible and also will not "age" 
because in five years
the dates look "outdated").

Any errors and/or bad English are mine only!

Please let me know whether this is helpful or not. If so, I will try to come up 
with the text for
the MutexSemaphore class in the next days.

Here it goes:

    5.4.x EventSemaphore Class

    Semaphores get used in multithreaded scenarios.

    An "event semaphore" allows one thread "A" to synchronize multiple threads
    (like "B", "C", ...) with whom the event semaphore gets shared.  Thread
    "A" creates the event semaphore and sends it the "reset" message.  Then
    thread "A" supplies the event semaphore to the threads "B", "C", ...,
    which each send the received event semaphore a "wait" message.  This will
    block the threads "B", "C", ..., until thread "A" sends the "post" message
    to the event semaphore.  At this time all threads waiting on the event
    semaphore get released and can run in parallel on their threads.

    5.4.x.1 close

    >>--- close ---><

    Closes the event semaphore.

    5.4.x.2 isPosted

    >>--- isPosted ---><

    Returns .true if the event semaphore is in the "posted" state, such that
    sending the "wait" message to this event semaphore would return
    immediately.  A return value of .false indicates that the event semaphore
    is not in the "posted" state, such that a "wait" message will block.

    5.4.x.2 post

    >>--- post ---><

    Sets the event semaphore to the "posted" state, signalling that the event
    that other threads are waiting on has occurred, such that all threads
    waiting on this event semaphore will be released and start to run again.

    5.4.x.3 reset

    >>--- reset ---><

    Resets (clears) the event semaphore to the non-"posted" state, such that 
    messages to this event semaphore will block.

    5.4.x.4 uninit

    >>--- uninit ---><

    This method cleans up the object when it is garbage collected.  It should
    not be invoked directly except via an uninit method of a subclass of the
    EventSemaphore class.

    5.4.x.5 wait

    >>--- wait(--+-------------+--)---><
                 |             |
                 +-- timeout --+

    Waits (blocks) on the event semaphore until it gets "posted".  If
    "timeout" was supplied it must be a whole number that represents the
    milliseconds to wait on the event semaphore before returning.

    If no "timeout" value was supplied or its value is negative, the wait will
    be forever, ie. until the event semaphore gets posted.

    If the "timeout" value is zero the method returns immediately with the
    same value that the method "isPosted" would return if sent to the event
    semaphore instead.

    The method returns .true if the event semaphore got "posted", .false if
    the method returns prematurely because the given timeout has occurred.


    The following example will fetch the routine object "WORKER" and in a loop
    will send the routine object the message "start" (defined in the ooRexx
    root class "Object") supplying the message name ("call") to be sent on a
    new (asynchroneous) thread, and as arguments the event semaphore to wait
    on and the number of the loop for the respective asynchroneous message.

    The main program creates an event semaphore and sends the message "reset"
    to it.  Then it sends the "start" message three times to the routine
    object in the loop, causing the routine "worker" to run on three different
    threads, where in each thread the executed routine then waits on the event
    semaphore ("wait" message to the event semaphore).  The main program then
    sleeps for five seconds, before sending the "post" message to the event
    semaphore, which will awake the routines on the three threads, ie.  they
    return from the wait message and execute on their threads in parallel,
    causing each to sleep for two seconds before returning from the routine

            eventSem=.eventSemaphore~new  -- create an event semaphore, will be 
in posted state
            dt=.dateTime~new     -- a .DateTime object to allow measuring 
elapsed time
            say "/main\     "  pp(dt~elapsed) "currently 'eventSem~isPosted':" 
            eventSem~reset       -- reset event semaphore, such that "wait" 
will block
            say "/main\     "  pp(dt~elapsed) "after 'eventSem~reset', 
'eventSem~isPosted':" pp(eventSem~isPosted)

            w=.routines~waiter   -- get routine 'WAITER' as a routine object
            do i=1 to 3
               say "/main\     "  pp(dt~elapsed)   "running routine 'WAITER' #" 
pp(i) "asynchroneously"
               w~start("call", eventSem, i)  -- call (run) the routine object 
on a separate thread

            say "/main\     "  pp(dt~elapsed)  "sleeping" pp(sleepTime) 
"seconds ..."
            call sysSleep sleepTime -- sleep five seconds

            say "/main\     "  pp(dt~elapsed)  "awoke, about doing an 
'eventSem~post' ..."
            eventSem~post        -- wake up all threads waiting on this event 
            say "\main/     "  pp(dt~elapsed)  "--> leaving main, other threads 
may still be active!"

            ::routine waiter     -- this routine will be called on a separate 
               use arg eventSem, nr
               s=.dateTime~new   -- we use our own .DateTime object to measure 
elapsed time on this thread
               say .context~name" #" nr":" pp(s~elapsed) "arrived, 
eventSem~isPosted="pp(eventSem~isPosted)", waiting..."
               eventSem~wait     -- wait until main program posts this event 

               say .context~name" #" nr":" pp(s~elapsed) "wait over, 
'eventSem~isPosted':" pp(eventSem~isPosted)
               say .context~name" #" nr":" pp(s~elapsed) "now sleeping" 
pp(sleepTime) "second(s)"
               call syssleep sleeptime -- sleep a second

               say .context~name" #" nr":" pp(s~elapsed) "sleep over"

            ::routine pp         -- "pretty print" ;) (encloses argument in 
square brackets)
              return "["arg(1)"]"

    Running this program may yield the following output:

            /main\      [00:00:00.000000] currently 'eventSem~isPosted': [1]
            /main\      [00:00:00.015000] after 'eventSem~reset', 
'eventSem~isPosted': [0]
            /main\      [00:00:00.015000] running routine 'WAITER' # [1] 
            /main\      [00:00:00.015000] running routine 'WAITER' # [2] 
            WAITER # 1: [00:00:00.000000] arrived, eventSem~isPosted=[0], 
            /main\      [00:00:00.015000] running routine 'WAITER' # [3] 
            WAITER # 2: [00:00:00.016000] arrived, eventSem~isPosted=[0], 

            WAITER # 3: [00:00:00.000000] arrived, eventSem~isPosted=[0], 
            /main\      [00:00:00.047000] sleeping [5] seconds ...
            /main\      [00:00:05.054000] awoke, about doing an 'eventSem~post' 

            \main/      [00:00:05.054000] --> leaving main, other threads may 
still be active!
            WAITER # 2: [00:00:05.039000] wait over, 'eventSem~isPosted': [1]
            WAITER # 1: [00:00:05.039000] wait over, 'eventSem~isPosted': [1]
            WAITER # 3: [00:00:05.023000] wait over, 'eventSem~isPosted': [1]
            WAITER # 2: [00:00:05.055000] now sleeping [2] second(s)
            WAITER # 1: [00:00:05.055000] now sleeping [2] second(s)
            WAITER # 3: [00:00:05.039000] now sleeping [2] second(s)
            WAITER # 3: [00:00:07.067000] sleep over
            WAITER # 1: [00:00:07.083000] sleep over
            WAITER # 2: [00:00:07.083000] sleep over


Oorexx-devel mailing list

Reply via email to