Annotation of os232sdk/toolkt20/c/samples/semaph/semaph.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.