home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / os2 / semaph / semaph.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  27KB  |  625 lines

  1. /*static char *SCCSID = "@(#)semaph.c   6.12 92/02/19";*/
  2. /*==============================================================*\
  3.  *  SEMAPH.C - routines for demonstrating semaphore API.        *
  4.  *        (C) Copyright IBM Corporation 1992.                   *
  5.  *--------------------------------------------------------------*
  6.  *  This module contains code to demonstrate the use of         *
  7.  *  semaphores to control access to a resource shared by        *
  8.  *  multiple threads. Event semaphores are used to signal a     *
  9.  *  thread is to give up a resource. A Mutex semaphore is used  *
  10.  *  to provide exclusive access to the resource. A mux          *
  11.  *  semaphore provides a method to check multiple event         *
  12.  *  semaphores.                                                 *
  13.  *                                                              *
  14.  *                                                              *
  15.  *--------------------------------------------------------------*
  16.  *                                                              *
  17.  *  This source file contains the following functions:          *
  18.  *                                                              *
  19.  *        VOID   SemError(PSZ,ULONG);                           *
  20.  *        ULONG  CreateAllSems(VOID);                           *
  21.  *        VOID   StartSemExample(VOID);                         *
  22.  *        VOID   ThreadConsumer(PVOID);                         *
  23.  *        VOID   SignalUserEvent(PULONG pfAutoMode);            *
  24.  *        ULONG  SetAutoMode(VOID);                             *
  25.  *        VOID   RunAuto(VOID);                                 *
  26.  *        VOID   StopSemaphore(VOID);                           *
  27.  *--------------------------------------------------------------*
  28.  * History:                                                     *
  29.  *                                                              *
  30.  * DEFECT    OWNER       Description                            *
  31.  * 84624     FHASAN      Mismatch data type     @mmdt           *
  32.  *                                                              *
  33.  *                                                              *
  34.  *                                                              *
  35. \*==============================================================*/
  36.  
  37. /*--------------------------------------------------------------*\
  38.  *  Include files, macros, defined constants, and externs       *
  39. \*--------------------------------------------------------------*/
  40. #include "semaph.h"
  41.  
  42. /*--------------------------------------------------------------*\
  43.  *  Global variables                                            *
  44. \*--------------------------------------------------------------*/
  45. extern LONG colors[MAXUSERS];
  46. extern LONG clrText[MAXUSERS];
  47. static VOID MyMove (ULONG ulMyID, ULONG ulUser);
  48.  
  49. /****************************************************************\
  50.  * Procedure to print error messages to screen in a Message Box.*
  51.  *--------------------------------------------------------------*
  52.  *                                                              *
  53.  *  Name:    SemError(pszAPIName,usErrorCode)                   *
  54.  *                                                              *
  55.  *  Purpose: Used to print name of API and error number when    *
  56.  *           a return code other than 0 is returned from an     *
  57.  *           API call.                                          *
  58.  *                                                              *
  59.  *  Usage:   Called by all procedures in this file whenever     *
  60.  *           an API call fails.                                 *
  61.  *                                                              *
  62.  *  Method:  The error number is converted to a string.  String *
  63.  *           functions are used to build the error message.     *
  64.  *           The message is printed in a Message Box.           *
  65.  *                                                              *
  66.  *  NOTE:    This function is called by multiple threads,       *
  67.  *           therefore, only re-entrant functions can be used.  *
  68.  *           Note that string is build according to American    *
  69.  *           English conventions using hard-coded strings, and  *
  70.  *           so portability to other languages would require a  *
  71.  *           more flexible approach.                            *
  72.  *                                                              *
  73.  *  Returns: none.                                              *
  74.  *                                                              *
  75. \****************************************************************/
  76. VOID SemError(PSZ pszAPIName,ULONG usErrorCode)
  77. {
  78.    char acMessage[100],acErrorNumber[10];
  79.  
  80.    _itoa(usErrorCode,acErrorNumber,BASETEN);
  81.    strcpy(acMessage,pszAPIName);
  82.    strcat(acMessage,": error # ");
  83.    strcat(acMessage,acErrorNumber);
  84.  
  85.    WinMessageBox(HWND_DESKTOP,
  86.                  hwndMain,
  87.                  acMessage,
  88.                  szAppName,
  89.                  1,
  90.                  MB_OK);
  91.    return;
  92. }
  93.  
  94. /****************************************************************\
  95.  * Routine to create  semaphores used in this file.             *
  96.  *--------------------------------------------------------------*
  97.  *                                                              *
  98.  *  Name:    CreateAllSems(VOID)                                *
  99.  *                                                              *
  100.  *  Purpose: Create semaphores needed by the consumer threads.  *
  101.  *           Checks return codes from semaphore creation.       *
  102.  *                                                              *
  103.  *  Usage:   Called by StartSemExample.                         *
  104.  *                                                              *
  105.  *  Method:  Semaphores are all anonymous private semaphores    *
  106.  *           since the semaphores are used by threads in the    *
  107.  *           same process.                                      *
  108.  *                                                              *
  109.  *  Returns: 0 if all semaphores are created successfully.      *
  110.  *           Otherwise returns error code for first create      *
  111.  *           semaphore API to fail.                             *
  112.  *                                                              *
  113. \****************************************************************/
  114. ULONG CreateAllSems(VOID)
  115. {
  116.    ULONG      rc;
  117.    SEMRECORD   asr[MAXRESOURCES];
  118.    INT         i;
  119.  
  120.    rc = DosCreateMutexSem((PSZ)NULL,&hmtxOwnResource, 0L,FALSE);
  121.    if (rc)
  122.    {
  123.        SemError("DosCreateMutexSem",rc);
  124.        return(rc);
  125.    }
  126.  
  127.    for (i = 0; i < MAXRESOURCES; i++)
  128.    {
  129.       rc = DosCreateEventSem( (PSZ)NULL, &aSquares[i].hev,
  130.                                       0L, FALSE);
  131.       if (rc)
  132.       {
  133.           SemError("DosCreateEventSem",rc);
  134.           return(rc);
  135.       }
  136.       else
  137.       {
  138.           asr[i].ulUser = i;
  139.           asr[i].hsemCur = (VOID *)aSquares[i].hev;
  140.       }
  141.    }
  142.                           /* this muxwait semaphore contains all of the
  143.                           event semaphores created in the loop above. */
  144.    rc = DosCreateMuxWaitSem((PSZ)NULL,&hmuxResource,
  145.            MAXRESOURCES,asr, DCMW_WAIT_ANY);
  146.    if (rc)
  147.    {
  148.       SemError("DosCreateMuxWaitSem",rc);
  149.       return(rc);
  150.    }
  151.    rc = DosCreateEventSem((PSZ)NULL,&hevStop,0L,FALSE);
  152.    if (rc)
  153.    {
  154.        SemError("DosCreateEventSem",rc);
  155.        return(rc);
  156.    }
  157.    return(rc);
  158. }
  159.  
  160. /****************************************************************\
  161.  * Routine to start semaphore example                           *
  162.  *--------------------------------------------------------------*
  163.  *                                                              *
  164.  *  Name:     StartSemExample(VOID)                             *
  165.  *                                                              *
  166.  *  Purpose:  Calls routines to create semaphores and draw      *
  167.  *            resources.  Creates consumer threads.             *
  168.  *                                                              *
  169.  *  Usage:    Called in file usercmd.c when the user selects    *
  170.  *            start from the semaphore menu.                    *
  171.  *                                                              *
  172.  *  Method:   Uses routines in paint.c to draw consumers and    *
  173.  *            resources.  This is done by creating a paint      *
  174.  *            message, not calling the draw routines directly.  *
  175.  *                                                              *
  176.  *  Returns:  TRUE if start succeeds, FALSE if start fails      *
  177.  *                                                              *
  178. \****************************************************************/
  179. INT   StartSemExample(VOID)
  180. {
  181.     TID         tid=0;
  182.     ULONG       rc;
  183.     INT         i;
  184.     FONTMETRICS fntmet;
  185.     HPS         hps;
  186.     SWP         swp;
  187.  
  188.     InitSemaphExample();
  189.  
  190.     rc = CreateAllSems();
  191.  
  192.     if (rc)
  193.         return FALSE;
  194.     /****************************************************************\
  195.      * Create consumer threads. Note that values can be passed to   *
  196.      * threads in OS/2 2.0. We pass the ordinal number of the child *
  197.      * to each child.                                               *
  198.     \****************************************************************/
  199.  
  200.     for (usConsumerThreadsCreated = 0;
  201.      usConsumerThreadsCreated < cNumUsers; usConsumerThreadsCreated++)
  202.     {
  203.         rc = DosCreateThread((PTID) &tid, (PFNTHREAD)ThreadConsumer,
  204.              (ULONG) usConsumerThreadsCreated, (ULONG)1,(ULONG) STACKSIZE);
  205.         if (rc)
  206.         {
  207.             SemError("DosCreateThread",rc);
  208.             return FALSE;
  209.         }
  210.         else
  211.         {
  212.             thrConsumers[usConsumerThreadsCreated].tid = tid;
  213.             thrConsumers[usConsumerThreadsCreated].lHits = 0L;
  214.         }
  215.     }
  216.     for (i = 0; i < (INT) cNumUsers; i++)
  217.     {
  218.         DosResumeThread (thrConsumers[i].tid);
  219.     }
  220.     hps = WinGetPS (hwndMain);
  221.     if (hps)
  222.     {
  223.         GpiQueryFontMetrics (hps, (LONG) sizeof fntmet, &fntmet);
  224.         WinQueryWindowPos (hwndMain, &swp);
  225.         SetRectPositions((SHORT)swp.cx, (SHORT)swp.cy,
  226.                          (SHORT) fntmet.lMaxBaselineExt,
  227.                          (SHORT) fntmet.lMaxDescender);
  228.         DrawRects (hps);
  229.         WinReleasePS (hps);
  230.     }
  231.     return TRUE;
  232. }
  233.  
  234. /****************************************************************\
  235.  * Routine to signal consumer to release resource.              *
  236.  *--------------------------------------------------------------*
  237.  *                                                              *
  238.  *  Name:     SignalUserEvent(pfAutoMode)                       *
  239.  *                                                              *
  240.  *  Purpose:  Posts user event semaphore to signal thread to    *
  241.  *            release resource.  Also posts event to stop       *
  242.  *            Auto mode if *pfAutoMode is true.                 *
  243.  *                                                              *
  244.  *  Usage:    Called in file usercmd.c when the user selects    *
  245.  *            Event from the semaphore menu.                    *
  246.  *                                                              *
  247.  *  Method:   Turns off Auto mode, if present by posting auto   *
  248.  *            semaphore.  User event is then posted.            *
  249.  *                                                              *
  250.  *  Returns:                                                    *
  251.  *                                                              *
  252. \****************************************************************/
  253. VOID SignalUserEvent(PULONG pfAutoMode)
  254. {
  255.   ULONG rc;
  256.  
  257.                           /* If sample is in auto mode turn auto mode off. */
  258.   if (*pfAutoMode)
  259.   {
  260.       rc = DosPostEventSem(hevStopAuto);
  261.       if (rc)
  262.       {
  263.          SemError("DosPostEventSem Stop Auto",rc);
  264.       }
  265.                        /* Wait for auto mode thread to die, so we don't
  266.                           end up with multiple copies of it later.    */
  267.  
  268.       rc = DosWaitThread(&tidAutoThread,0L);
  269.       if (rc)
  270.       {
  271.          SemError("DosWaitThread",rc);
  272.       }
  273.       *pfAutoMode = FALSE;
  274.       DosCloseEventSem (hevStopAuto);
  275.   }
  276.  
  277.   /* If Auto mode haas already posted the event this is OK
  278.      so we will not check error codes here. */
  279.  
  280.   DosPostEventSem(aSquares[rand() % MAXRESOURCES].hev);
  281.   return;
  282. }
  283.  
  284. /****************************************************************\
  285.  * Routine to start Auto mode.                                  *
  286.  *--------------------------------------------------------------*
  287.  *                                                              *
  288.  *  Name:     SetAutoMode(VOID)                                 *
  289.  *                                                              *
  290.  *  Purpose:  Creates thread and semaphore needed to run auto   *
  291.  *            mode.                                             *
  292.  *                                                              *
  293.  *  Usage:    Called in file usercmd.c when the user selects    *
  294.  *            Auto from the semaphore menu.                     *
  295.  *                                                              *
  296.  *  Returns:  NO_ERROR on success, else error from api call.    *
  297.  *                                                              *
  298. \****************************************************************/
  299. ULONG SetAutoMode()
  300. {
  301.     ULONG rc;
  302.  
  303.     rc = DosCreateEventSem((PSZ)NULL,&hevStopAuto,0L,FALSE);
  304.     if (rc)
  305.     {
  306.         SemError("DosCreateEventSem",rc);
  307.         return(rc);
  308.     }
  309.  
  310.     rc = DosCreateThread((PTID)&tidAutoThread,(PFNTHREAD)RunAuto,0L,0L,STACKSIZE);
  311.     if (rc)
  312.     {
  313.         DosCloseEventSem (hevStopAuto); /* close semaphore created above */
  314.         SemError("DosCreateThread", rc);
  315.         return(rc);
  316.     }
  317.  
  318.     return(NO_ERROR);
  319. }
  320.  
  321. /****************************************************************\
  322.  * Routine to run Auto mode.                                    *
  323.  *--------------------------------------------------------------*
  324.  *                                                              *
  325.  *  Name:     RunAuto(PVOID pvArg)                              *
  326.  *                                                              *
  327.  *  Purpose:  Posts user event at fixed time interval to signal *
  328.  *            consumers to release resource.                    *
  329.  *                                                              *
  330.  *  Usage:    Thread created by SetAutoMode.                    *
  331.  *                                                              *
  332.  *  Method:   Kills itself when StopAutoMode semaphore is       *
  333.  *            posted.                                           *
  334.  *                                                              *
  335.  *  Returns:                                                    *
  336.  *                                                              *
  337. \****************************************************************/
  338. VOID RunAuto( PVOID pvArg )
  339. {
  340.    ULONG rcWait;
  341.    HAB habLocal;
  342.    HMQ hmqLocal;
  343.    INT i;
  344.  
  345.    /* Need a message queue for any thread that wants to print messages. */
  346.  
  347.    habLocal = WinInitialize(0);
  348.    hmqLocal = WinCreateMsgQueue(habLocal,0);
  349.  
  350.    /* while stop auto semaphore not posted, post user event semaphore. */
  351.  
  352.       /***************************************************************
  353.        * Don't check return code from DosPostEventSem(hevUserEvent)  *
  354.        * since we just want the resource to change hands.  We don't  *
  355.        * care if it changes hands exactly every time it goes through *
  356.        * the loop.                                                   *
  357.        *                                                             *
  358.        * The event may already be posted if the system is busy and   *
  359.        * the resource threads don't finish with it fast enough.      *
  360.        * This is not a problem in this case.                         *
  361.        ***************************************************************/
  362.  
  363.    do {                      /* if ulTimeout is zero, still waitevent
  364.                                  for 1 msec to force yielding of CPU. */
  365.        rcWait = DosWaitEventSem(hevStopAuto, max (ulTimeout, 1));
  366.        if (rcWait == ERROR_TIMEOUT)
  367.        {
  368.            i = rand () % MAXRESOURCES;      /* generate it */
  369.            DosPostEventSem (aSquares[i].hev);
  370.        }
  371.    } while (rcWait == ERROR_TIMEOUT);
  372.  
  373.    /* If there was an error, print a message */
  374.  
  375.    if (rcWait)
  376.    {
  377.       SemError("DosWaitEventSem",rcWait);
  378.    }
  379.  
  380.    WinDestroyMsgQueue (hmqLocal);
  381.    WinTerminate (habLocal);
  382.    DosExit(EXIT_THREAD,0);
  383.  
  384.    return;
  385. }
  386.  
  387. /****************************************************************\
  388.  * Routine to stop semaphore example.                           *
  389.  *--------------------------------------------------------------*
  390.  *                                                              *
  391.  *  Name:     BeginStop(pfAutoMode)                             *
  392.  *                                                              *
  393.  *  Purpose:  Posts stop event semaphore to signal threads to   *
  394.  *            die.  Also posts event to stop Auto mode if       *
  395.  *            necessary. Then waits for threads to complete,    *
  396.  *            Creates thread StopSemaphore which posts stop     *
  397.  *            event and waits for child threads.                *
  398.  *                                                              *
  399.  *  Usage:    Called in file usercmd.c when the user selects    *
  400.  *            Stop from the semaphore menu.                     *
  401.  *                                                              *
  402.  *  Method:   Execs thread to do waits so that message thread   *
  403.  *            doesn't hang.                                     *
  404.  *  Returns:                                                    *
  405.  *                                                              *
  406. \****************************************************************/
  407. VOID BeginStop (PULONG pfAutoMode)
  408. {
  409.    ULONG rc;
  410.    TID tidLocal;
  411.  
  412.    rc = DosPostEventSem(hevStop);
  413.    if (rc)
  414.    {
  415.        SemError("DosPostEventSem",rc);
  416.        return;
  417.    }
  418.    if (*pfAutoMode)
  419.    {
  420.        rc = DosPostEventSem(hevStopAuto);
  421.        if (rc)
  422.        {
  423.           SemError("DosPostEventSem",rc);
  424.        }
  425.    }
  426.    rc = DosCreateThread((PTID)&tidLocal, (PFNTHREAD)StopSemaphore,
  427.                           (ULONG)pfAutoMode,(ULONG)0,(ULONG) STACKSIZE);
  428.    if (rc)
  429.    {
  430.        SemError("DosCreateThread",rc);
  431.    }
  432.    return;
  433. }
  434.  
  435. /****************************************************************\
  436.  * Routine to really stop semaphore example.                    *
  437.  *--------------------------------------------------------------*
  438.  *                                                              *
  439.  *  Name:     StopSemaphore( PVOID pvArg )                      *
  440.  *                                                              *
  441.  *  Purpose:  Waits for threads to complete,                    *
  442.  *            Sends message to message thread to indicate this  *
  443.  *            has occurred, and exits.                          *
  444.  *                                                              *
  445.  *  Usage:    Exec'd from BeginStop when user selects Stop from *
  446.  *            Semaphore menu.                                   *
  447.  *                                                              *
  448.  *  Method:   Turns off Auto mode, if present by posting auto   *
  449.  *            semaphore.  Then stop event is posted.  Waits     *
  450.  *            for threads to die.                               *
  451.  *  Returns:                                                    *
  452.  *                                                              *
  453. \****************************************************************/
  454. VOID StopSemaphore( PVOID pvArg )
  455. {
  456.    ULONG rc,usCount, i;
  457.    PULONG pfAutoMode = (PULONG)pvArg;
  458.  
  459.    if (*pfAutoMode)
  460.    {
  461.       rc = DosWaitThread(&tidAutoThread,0L);
  462.       if (rc && (rc != ERROR_INVALID_THREADID))
  463.       {
  464.          SemError("DosWaitThread",rc);
  465.       }
  466.       *pfAutoMode = FALSE;
  467.    }
  468.    /* Wait for usConsumer threads to die.  Order of death not important. */
  469.  
  470.    for (usCount = 0; usCount < usConsumerThreadsCreated; usCount++)
  471.    {
  472.       rc = DosWaitThread(&thrConsumers[usCount].tid,0L);
  473.  
  474.       /* rc is ERROR_INVALID_THREADID the thread is already dead.*\
  475.       \* This is OK and not a error.                             */
  476.  
  477.       if (rc && (rc != ERROR_INVALID_THREADID))
  478.       {
  479.          SemError("DosWaitThread",rc);
  480.       }
  481.    }
  482.                 /* Threads dead so we don't need semaphores any more.  */
  483.    DosCloseEventSem(hevStopAuto);
  484.    DosCloseEventSem(hevStop);
  485.    DosCloseMutexSem(hmtxOwnResource);
  486.    for (i = 0; i < MAXRESOURCES; i++)
  487.    {
  488.       DosCloseEventSem(aSquares[i].hev);
  489.    }
  490.    DosCloseMuxWaitSem (hmuxResource);
  491.    WinPostMsg (hwndMain, WM_COMMAND, (MPARAM)IDM_STOPFINISHED, (MPARAM)NULL);
  492.    DosExit (EXIT_THREAD, 0);
  493.    return;
  494. }
  495.  
  496. /****************************************************************\
  497.  * Routine for consumer threads.                                *
  498.  *--------------------------------------------------------------*
  499.  *                                                              *
  500.  *  Name:     ThreadConsumer(PVOID)                             *
  501.  *                                                              *
  502.  *  Purpose:  There are NUMUSERS copies of this thread to act   *
  503.  *            as consumers of the resource. The thread waits for*
  504.  *            exclusive access to the resource and colors it.   *
  505.  *                                                              *
  506.  *  Usage:    Threads created by StartSemExample.               *
  507.  *                                                              *
  508.  *  Method:   Waits for mutex to gain ownership of resource.    *
  509.  *            Releases resource when user event. Dies when      *
  510.  *            Stop event.                                       *
  511.  *  Returns:                                                    *
  512.  *                                                              *
  513. \****************************************************************/
  514. VOID ThreadConsumer( PVOID pvMyID )
  515. {
  516.    ULONG  ulPostCnt;
  517.    ULONG  ulUser=0L;
  518.    ULONG  rc;
  519.    HAB    habb;
  520.    HMQ    hmqq;
  521.  
  522.    /* Need a message queue for any thread that wants to print messages. */
  523.    habb = WinInitialize(0);
  524.    hmqq = WinCreateMsgQueue(habb,0);
  525.  
  526.    /* while the user has not selected stop ... */
  527.    while ((DosWaitEventSem(hevStop,SEM_IMMEDIATE_RETURN)) == ERROR_TIMEOUT)
  528.    {
  529.       /* Wait for exclusive ownership of resource */
  530.  
  531.       DosRequestMutexSem(hmtxOwnResource,SEM_INDEFINITE_WAIT);
  532.  
  533.       /* the following check is necessary because the stop semaphore
  534.        * may have been posted  while we were waiting on the mutex
  535.        */
  536.       if (DosWaitEventSem(hevStop, SEM_IMMEDIATE_RETURN) == ERROR_TIMEOUT)
  537.       {
  538.       /*********************************************************************\
  539.        * an item is ready, which one?  don't wait forever because there is *
  540.        * a possibility that the stop semaphore was posted and that no more *
  541.        * resource is forthcoming. we wait twice as long as we think is     *
  542.        * necessary.                                                        *
  543.       \*********************************************************************/
  544.          if (!DosWaitMuxWaitSem (hmuxResource, max (ulTimeout << 1,
  545.             TIMEOUTPERIOD) , &ulUser))
  546.          {
  547.             MyMove ((ULONG) pvMyID, ulUser);
  548.             DosResetEventSem(aSquares[ulUser].hev, &ulPostCnt);
  549.          }
  550.       }
  551.                                /* Let some other thread have resource. */
  552.       rc = DosReleaseMutexSem(hmtxOwnResource);
  553.       if (rc)
  554.       {
  555.          SemError("DosReleaseMutexSem",rc);
  556.       }
  557.    }
  558.    /* hevStop was posted, kill this thread */
  559.    WinDestroyMsgQueue (hmqq);
  560.    WinTerminate (habb);
  561.    DosExit(EXIT_THREAD, 0);
  562.    return;
  563. }
  564.  
  565. /****************************************************************\
  566.  *  called from ThreadConsumer to make and register move        *
  567.  *--------------------------------------------------------------*
  568.  *                                                              *
  569.  *  Name: MyMove (ulMyID, ulUser)                               *
  570.  *        ULONG     ulMyID;     id of caller                    *
  571.  *        ULONG     ulUser;     number of the square to "hit"   *
  572.  *                                                              *
  573.  *  Purpose: color a square on the game board 'my' color.       *
  574.  *           update display of number of hits for 'my' thread.  *
  575.  *                                                              *
  576.  *  Usage: called only from ThreadConsumer                      *
  577.  *                                                              *
  578.  *  Method:                                                     *
  579.  *                                                              *
  580.  *  Returns: none                                               *
  581.  *                                                              *
  582. \****************************************************************/
  583. static VOID MyMove (ULONG ulMyID, ULONG ulUser)
  584. {
  585.    if (aSquares [ulUser].usOwner != ulMyID)
  586.    {
  587.       aSquares[ulUser].usOwner = ulMyID;
  588.       thrConsumers[ulMyID].lHits++;
  589.       DrawResource (&aSquares[ulUser].rcl, colors [ulMyID]);
  590.       DrawStats (ulMyID);
  591.    }
  592.    return;
  593. }
  594.  
  595. /****************************************************************\
  596.  * Routine to init game board                                   *
  597.  *--------------------------------------------------------------*
  598.  *                                                              *
  599.  *  Name:     InitSemaphExample(VOID)                           *
  600.  *                                                              *
  601.  *  Purpose:  Initializes game board unowned, sets semaphores   *
  602.  *            to 0.                                             *
  603.  *  Usage:    Called from StartSemExample in semaph.c when      *
  604.  *            user selects start from the semaphore menu.       *
  605.  *  Method:                                                     *
  606.  *                                                              *
  607.  *  Returns:  none                                              *
  608.  *                                                              *
  609. \****************************************************************/
  610. VOID InitSemaphExample(VOID)
  611. {
  612.    int i;
  613.  
  614.    for (i = 0; i < MAXRESOURCES; i++)
  615.    {
  616.       aSquares[i].hev = 0;
  617.       aSquares[i].usOwner = UNOWNED;
  618.    }
  619.    hevStopAuto = 0L;
  620.    hevStop = 0L;
  621.    hmtxOwnResource = 0L;
  622.    hmuxResource  = 0L;
  623.    return;
  624. }
  625.