Product SiteDocumentation Site

12.4.4. Additional Examples

The following example uses REPLY in a method for a write-back cache.

Example 12.6. Method Write_Back

/* Method Write_Back                                 */
use arg data           /* Save data to be written    */
reply 0                /* Tell the sender all was OK */
self~disk_write(data)  /* Now write the data         */

The REPLY instruction returns control to the point at which method Write_Back was called, returning the result 0. The caller of method Write_Back continues processing from this point; meanwhile, method Write_Back also continues processing.
The following example uses a message object. It reads a line asynchronously into the variable nextline:

Example 12.7. Message to INFILE

mymsg = infile~start("READLINE") /* Gets message object to carry    */
/* message to INFILE                                                */
/* do other work */
nextline=mymsg~result            /* Gets result from message object */

This creates a message object that waits for the read to finish while the sender continues with other work. When the line is read, the mymsg message object obtains the result and holds it until the sender requests it.
Semaphores and monitors (bounded buffers) synchronize concurrency processes. Giving readers and writers concurrent access is a typical concurrency problem. The following sections show how to use guarded methods to code semaphore and monitor mechanisms and to provide concurrency for readers and writers.

12.4.4.1. Semaphores

A semaphore is a mechanism that controls access to resources, for example, preventing simultaneous access. Synchronization often uses semaphores. Here is an example of a semaphore class:

Example 12.8. Example of a Rexx Semaphore Class

/*******************************************************************************/
/*  A Rexx Semaphore Class.                                                    */
/*                                                                             */
/* This file implements a semaphore class in Rexx.  The class is defined to    */
/* the Global Rexx Environment.  The following methods are defined for         */
/* this class:                                                                 */
/*   init - Initializes a new semaphore.  Accepts the following positional     */
/*          parameters:                                                        */
/*                             'name' - global name for this semaphore         */
/*                                if named default to set name in              */
/*                                the class semDirectory                       */
/*                             noshare -  do not define named semaphore        */
/*                                in class semDirectory                        */
/*                             Initial state (0 or 1)                          */
/*   setInitialState - Allow for subclass to have some post-initialization,    */
/*     and do setup based on initial state of semaphore                        */
/*   Waiting  - Is the number of objects waiting on this semaphore.            */
/*   Shared   - Is this semaphore shared (Global).                             */
/*   Named    - Is this semaphore named.                                       */
/*   Name     - Is the name of a named semaphore.                              */
/*   setSem   - Sets the semaphore and returns previous state.                 */
/*   resetSem - Sets state to unSet.                                           */
/*   querySem - Returns current state of semaphore.                            */
/*                                                                             */
/* SemaphoreMeta - Is the metaclass for the semaphore classes.  This class is  */
/*   set up so that when a namedSemaphore is shared, it maintains these        */
/*   named/shared semaphores as part of its state.  These semaphores are       */
/*   maintained in a directory, and an UNKNOWN method is installed on the      */
/*   class to forward unknown messages to the directory.  In this way the      */
/*   class can function as a class and "like" a directory, so [] syntax can    */
/*   be used to retrieve a semaphore from the class.                           */
/*                                                                             */
/*                                                                             */
/* The following are in the subclass EventSemaphore.                           */
/*                                                                             */
/*   Post  - Posts this semaphore.                                             */
/*   Query - Queries the number of posts since the last reset.                 */
/*   Reset - Resets the semaphore.                                             */
/*   Wait  - Waits on this semaphore.                                          */
/*                                                                             */
/*                                                                             */
/* The following are in the subclass MutexSemaphore                            */
/*                                                                             */
/*   requestMutex - Gets exclusive use of semaphore.                           */
/*   releaseMutex - Releases to allow someone else to use semaphore.           */
/*        NOTE: Currently anyone can issue a release (need not be the owner).  */
/*******************************************************************************/
/* ============================================================================ */
/* ===         Start of Semaphore class.                                  ===== */
/* ============================================================================ */
::class SemaphoreMeta subclass class
::method init
  expose semDict
                                            /* Be sure to initialize parent     */
  .message~new(self, .array~of("INIT", super), "a", arg(1,"a"))~send
  semDict = .directory~new

::method unknown
  expose semDict
  use arg msgName, args
                                            /* Forward all unknown messages     */
                                            /* to the semaphore dictionary      */
  .message~new(semDict, msgName, "a", args)~send
  if var("RESULT") then
    return result
  else
    return


::class Semaphore subclass object metaclass SemaphoreMeta

::method init
  expose sem waits shared name
  use arg semname, shr, state

  waits = 0                                 /* No one waiting                   */
  name = ""                                 /* Assume unnamed                   */
  shared = 0                                /* Assume not shared                */
  sem = 0                                   /* Default to not posted            */

  if state = 1 Then                         /* Should initial state be set?     */
    sem = 1
                                            /* Was a name specified?            */
  if VAR("SEMNAME") & semname \= "" Then Do
    name = semname                          /* Yes, so set the name             */


    if shr \= "NOSHARE" Then Do             /* Do we want to share this sem?    */
      shared = 1                            /* Yes, mark it shared              */
                                            /* Shared add to semDict            */
      self~class[name] = self
    End

  End
  self~setInitialState(sem)                 /* Initialize initial state         */

::method setInitialState
                                            /* This method intended to be       */
nop                                         /* overridden by subclasses         */
::method setSem
expose sem
oldState = sem
sem = 1                                     /* Set new state to 1               */
return oldState

::method resetSem
expose sem
sem = 0
return 0

::method querySem
expose sem
return sem


::method shared
expose shared
return shared                               /* Return true 1 or false 0         */

::method named
expose name
                                            /* Does semaphore have a name?      */
if name = "" Then return 0                  /* No, not named                    */
Else return 1                               /* Yes, it is named                 */

::method name
expose name
return name                                 /* Return name or ""                */

::method incWaits
expose waits
waits = waits + 1                           /* One more object waiting          */

::method decWaits
expose Waits
waits = waits - 1                           /* One object less waiting          */

::method Waiting
expose Waits
return waits                                /* Return number of objects waiting */
/* ========================================================================== */
/* ===         Start of EventSemaphore class.                             === */
/* ========================================================================== */

::class EventSemaphore subclass Semaphore public
::method setInitialState
  expose posted posts
  use arg posted

  if posted  then posts = 1
  else posts = 0
::method post
  expose posts posted

  self~setSem                        /* Set semaphore state            */
  posted = 1                         /* Mark as posted                 */
  reply
  posts = posts + 1                  /* Increase the number of posts   */

::method wait
  expose posted

  self~incWaits                      /* Increment number waiting       */
  guard off
  guard on when posted               /* Now wait until posted          */
  reply                              /* Return to caller               */
  self~decWaits                      /* Cleanup, 1 less waiting        */

::method reset
  expose posts posted

  posted = self~resetSem             /* Reset semaphore                */
  reply                              /* Do an early reply              */
  posts = 0                          /* Reset number of posts          */

::method query
  expose posts
                                     /* Return number of times         */
  return posts                       /* Semaphore has been posted      */
/* ========================================================================== */
/* ===         Start of MutexSemaphore class.                             === */
/* ========================================================================== */

::class MutexSemaphore subclass Semaphore public

::method setInitialState
  expose owned
  use arg owned


::method requestMutex
  expose Owned

  Do forever                                /* Do until we get the semaphore  */
    owned = self~setSem
    if Owned = 0                            /* Was semaphore already set?     */
      Then leave                            /* Wasn't owned; we now have it   */
    else Do
      self~incWaits
      guard off                             /* Turn off guard status to let   */
                                            /* others come in                 */
      guard on when \Owned                  /* Wait until not owned and get   */
                                            /* guard                          */
      self~decWaits                         /* One less waiting for MUTEX     */
    End
                                            /* Go up and see if we can get it */
  End


::method releaseMutex
  expose owned
  owned = self~resetSem                     /* Reset semaphore                */

Note

There are functions available that use system semaphores. See Section 8.11, “SysCreateEventSem”, and Section 8.12, “SysCreateMutexSem”.