Menu

Using ooRexx sample semaphore class

Help
2013-07-05
2013-07-05
  • Tim Tierney

    Tim Tierney - 2013-07-05

    I am attempting to use the sample semaphore file 'semcls.rex' as supplied by ooRexx v4.1.2 in the \samples directory. If I run the following code snippet:

    /*-- REXX Procedure: testSem   --*/
    
    sHandl = .Semaphore~init( "tstSem" )
    Say  sHandl
    Exit 0
    
    ::Requires semcls.rex
    

    I receive the following error messages on the console:

       105 *-* .message~new(self, .array~of('INIT', super), 'a', arg(1,'a'))~send 
         3 *-* sHandl = .Semaphore~init( "tstSem" )
    Error 93 running D:\REXX\testSem.rex line 105:  Incorrect call to method
    Error 93.902:  Too many arguments in invocation of method; 0 expected
    

    The prolog of the class file contains the comments regarding the 'init' invocation:

    /*   init - initialize a new semaphore.  Will accept the following positional */
    /*          parameters:                                                       */
    /*                             'name' - global name for this semaphore        */
    /*                                if named default to set name in             */
    /*                                the class semDirectory                      */
    /*                             noshare -  don't define named semaphore        */
    /*                                into class semDirectory                     */
    /*                             Inital state (0 or 1)                          */
    

    In the above run of testSem I have embedded the contents of the 'semcls.rex' file so that all trace back messages will be emitted. The error 93 messages are emitted in either case.

    I'm sure that this is probably a misunderstanding on my part and any help will is appreciated. Thanks!

     
    • Mark Miesfeld

      Mark Miesfeld - 2013-07-05

      To instantiate a new object, you, usually, use the new() method. You don't invoke the init() method yourself.

      Change this:

      sHandl = .Semaphore~init( "tstSem" )

      to this:

      sHandl = .Semaphore~new( "tstSem" )

      and see what happens.

      If you still have problems, add your entire program as an attachment so that someone can take a look at it.

       
  • Tim Tierney

    Tim Tierney - 2013-07-05

    I thought that the init() method was driven when the new() method was invoked. That was my first attempt and it resulted in the following error (using the above code segment):

         3 *-* sHandl = .Semaphore~new( 'tstSem' )
    Error 97 running D:\REXX\testSem.rex line 3:  Object method not found
    Error 97.1:  Object ".SEMAPHORE" does not understand message "NEW"
    

    Since I am experimenting with the semaphore class I do not have much more to show in the way of functional code, however I have attached the source file that I am playing with.

     
  • Mark Miesfeld

    Mark Miesfeld - 2013-07-05

    Hi Tim,

    First off, the Semaphore class is not public. So when you do the requires in your program, the .Semaphore class is not visible. That's why you get the message about not understanding the message new.

    The class is not intended to be used the way you are trying. Rather you are expected to use one of the subclasses provided. Change your code to:

    /-- REXX Procedure: testSem --/

    sHandl = .MutexSemaphore~new( 'tstSem' )
    say 'requesting mutex'
    sHandl~RequestMutex

    Say 'got mutex, leaving now'
    Exit 0

    ::Requires semcls.rex

    You will get output similar to:

    requesting mutex
    got mutex, leaving now

    Which is expected, but at least you will now be on the right track.

    At the time you invoke RequestMutex(), nothing else is holding the mutex, so your code immediately gains the mutex and proceeds.

    Now you just need to figure out what to do with a mutex.

    Here is a simplistic program that shows a writer and a reader. You don't want the reader to read while the writer is writing. And vice versa. I'll also attach it.

    /-- REXX Procedure: holdMutex.rex --/

    sHandl = .MutexSemaphore~new( 'tstSem' )
    say 'created mutex'

    writer = .Writer~new(sHandl)
    reader = .Reader~new(sHandl)

    writer~work
    -- Let the writer get started
    j = SysSleep(.1)

    reader~work

    Exit 0

    ::Requires semcls.rex

    ::class 'Writer'

    ::method init
    expose mtx
    use arg mtx

    ::method write
    expose mtx

    say 'want to write, requsting mtx'

    mtx~requestMutex
    say 'Writer got mutex'
    do i = 1 to 5
    say 'writing' i
    r = SysSleep(1)
    end
    say 'writer releasing mutex'

    mtx~releaseMutex

    ::method work unguarded

    reply 0

    do 15
    self~write
    r = SysSleep(2)
    end

    ::class 'Reader'

    ::method init
    expose mtx
    use arg mtx

    ::method read
    expose mtx

    say 'want to read, requsting mtx'

    mtx~requestMutex
    say 'Reader got mutex'
    do i = 1 to 5
    say 'reading' i
    r = SysSleep(1)
    end
    say 'reader releasing mutex'

    mtx~releaseMutex

    ::method work unguarded

    reply 0

    do 15
    self~read
    r = SysSleep(2)
    end

     
  • Mark Miesfeld

    Mark Miesfeld - 2013-07-05

    Maybe I should have added a little explanation. If you look at the output from the example:

    ~~~~~~~~~~~~~~
    created mutex
    want to write, requsting mtx
    Writer got mutex
    writing 1
    want to read, requsting mtx
    writing 2
    writing 3
    writing 4
    writing 5
    writer releasing mutex
    Reader got mutex
    reading 1
    reading 2
    want to write, requsting mtx
    reading 3
    reading 4
    reading 5
    reader releasing mutex
    Writer got mutex
    writing 1
    writing 2
    want to read, requsting mtx
    writing 3
    writing 4
    writing 5
    writer releasing mutex
    Reader got mutex
    reading 1
    reading 2
    want to write, requsting mtx
    reading 3
    reading 4
    reading 5
    reader releasing mutex
    Writer got mutex
    ~~~~~~~~~~~~

    You can see that the reader never gets the mutex until the writer releases it.

    You can see that neither the reader nor the writer, even though they want to write or want to read, can read or write until the other is finished. You never get 'reading' interspersed with 'writing'. Each reader finishes all 5 reads without the writer writing anything while the reader is reading.

     
  • Tim Tierney

    Tim Tierney - 2013-07-05

    Hi Mike,

    Thanks for clearing up the mystery. Since I'm relatively new to the OO part of Rexx I thought that I probably wasn't looking at the problem properly.

    Your example code is largely what I wish to do with my code, with the exception that the "reader" and "writer" will be in infinite loops with a unique semaphore (EventSemaphore class) associated with each thread. [EDIT] The worker tasks will use a MutexSemaphore to control access to a common buffer [EDIT END]. There will be another concurrent "control" task that will post the worker semaphore when termination is required. When reactivating after the sleep interval, the worker tasks will simply query their semaphore to determine if it is time to wrap-up. The intent is to provide a server style function with external control. The ability to query a semaphore for the post count was the main reason for using "semcls.rex" in the first place.

    So thanks for the help and I may be back again if I get stuck.

     

    Last edit: Tim Tierney 2013-07-05

Log in to post a comment.