Annotation of q_a/samples/readwrit/database.c, revision 1.1

1.1     ! root        1: #define STRICT
        !             2: #define NOMINMAX
        !             3: #include <windows.h>
        !             4: #include <stdio.h>
        !             5: #include <string.h>
        !             6: #include <stdlib.h>
        !             7: 
        !             8: 
        !             9: typedef HANDLE HMUTEX ;
        !            10: typedef HANDLE HSEM ;
        !            11: typedef HANDLE HEVENT ;
        !            12: 
        !            13: /* Names for synchronization objects */
        !            14: #define SEM1    "semph1"
        !            15: #define MUTX1   "mutx1"
        !            16: #define EVENT1  "event1"
        !            17: #define EVENT2  "event2"
        !            18: #define EVENT3  "evnet3"
        !            19: #define EVENT4  "event4"
        !            20: 
        !            21: #define MAX     10
        !            22: 
        !            23: #define SIGNALED    0
        !            24: #define WAIT_ERROR  0xFFFFFFFF
        !            25: 
        !            26: 
        !            27: /*global Variables */
        !            28: int    gUserCount = 0 ;
        !            29: HMUTEX ghMutex ;
        !            30: HSEM   ghSemaphore ;
        !            31: HEVENT ghReadEvent1, ghReadEvent2, ghWriteEvent1, ghWriteEvent2 ;
        !            32: UINT   cReadQueue, cWriteQueue, cReadQueueEx ;
        !            33: UINT   cRead, cWrite ;
        !            34: BOOL   InWrite ;
        !            35: 
        !            36: /*
        !            37:  * This is the data type which this
        !            38:  *
        !            39:  */
        !            40: 
        !            41: char   *DataBase[MAX] ;
        !            42: 
        !            43: 
        !            44: 
        !            45: /***** Private functions *****/
        !            46: 
        !            47: BOOL InitializeSubsystem ( VOID ) ;
        !            48: BOOL InitApp ( VOID ) ;
        !            49: BOOL CleanupSubsystem ( VOID ) ;
        !            50: BOOL CleanupApp ( VOID ) ;
        !            51: BOOL InitializeDataBase ( VOID ) ;
        !            52: BOOL CloseDataBase ( VOID ) ;
        !            53: BOOL GetData ( PSZ psz ) ;
        !            54: BOOL PutData ( PSZ psz ) ;
        !            55: 
        !            56: 
        !            57: /***** DLL Entry/Exit point *****/
        !            58: 
        !            59: BOOL APIENTRY DLLInitExitPoint ( HANDLE hModule, DWORD dwReason, LPVOID lpReserved ) ;
        !            60: 
        !            61: 
        !            62: /***** Debuging functions *****/
        !            63: 
        !            64: VOID ErrorMsg ( PSZ psz ) ;
        !            65: VOID DebugMsg ( PSZ psz ) ;
        !            66: 
        !            67: 
        !            68: 
        !            69: /***** Public functions *****/
        !            70: 
        !            71: BOOL APIENTRY ReadDataBase  ( PSZ, PSZ ) ;
        !            72: BOOL APIENTRY WriteDataBase ( PSZ, PSZ ) ;
        !            73: 
        !            74: 
        !            75: 
        !            76: 
        !            77: 
        !            78: /***************************************************************************\
        !            79: **                                                                         **
        !            80: **   PROGRAM: DataBase                                                     **
        !            81: **                                                                         **
        !            82: **   PURPOSE: Demonstrates the basic concepts of one of the classical      **
        !            83: **            synchronous problems. A derivative of the Reader/Writer      **
        !            84: **            problem. In which one must allow access to each without      **
        !            85: **            jeopardizing the Database.                                   **
        !            86: **                                                                         **
        !            87: **   INTERNAL FUNCTIONS:                                                   **
        !            88: **                                                                         **
        !            89: **          InitializeDataBase                                             **
        !            90: **          CloseDataBase                                                  **
        !            91: **          InitializeSubsystem                                            **
        !            92: **          InitApp                                                        **
        !            93: **          CleanupSubsystem                                               **
        !            94: **          CleanupApp                                                     **
        !            95: **          TestInitExitPoint                                              **
        !            96: **          ErrorMsg                                                       **
        !            97: **          DebugMsg                                                       **
        !            98: **                                                                         **
        !            99: **                                                                         **
        !           100: **   EXPORTED FUNCTIONS                                                    **
        !           101: **                                                                         **
        !           102: **          ReadDataBase                                                   **
        !           103: **          WriteDataBase                                                  **
        !           104: **                                                                         **
        !           105: **                                                                         **
        !           106: **   COMMENTS:                                                             **
        !           107: **                                                                         **
        !           108: **          Currently this                                                 **
        !           109: **                                                                         **
        !           110: \***************************************************************************/
        !           111: 
        !           112: 
        !           113: 
        !           114: /***************************************************************************\
        !           115: **                                                                         **
        !           116: **   FUNCTION: ErrorMsg(LPTSTR)                                            **
        !           117: **                                                                         **
        !           118: **   PURPOSE: Prints out an error message the return code of the last API  **
        !           119: **            to fail.                                                     **
        !           120: **                                                                         **
        !           121: **   INPUT: psz: This string is a description of where the code failed in  **
        !           122: **          the module                                                     **
        !           123: **                                                                         **
        !           124: **   OUTPUT: None                                                          **
        !           125: **                                                                         **
        !           126: \****************************************************************************/
        !           127: 
        !           128: VOID ErrorMsg ( PSZ psz )
        !           129: {
        !           130:     printf ("\n%s: return code = %d\n", psz, GetLastError()) ;
        !           131: }
        !           132: 
        !           133: 
        !           134: /***************************************************************************\
        !           135: **                                                                         **
        !           136: **   FUNCTION: DebugMsg(LPTSTR)                                            **
        !           137: **                                                                         **
        !           138: **   PURPOSE: Prints out an debug message                                  **
        !           139: **                                                                         **
        !           140: **   INPUT: psz: This string is used for informational purposes only       **
        !           141: **                                                                         **
        !           142: **   OUTPUT: None                                                          **
        !           143: **                                                                         **
        !           144: \****************************************************************************/
        !           145: 
        !           146: 
        !           147: VOID APIENTRY DebugMsg ( PSZ psz )
        !           148: {
        !           149:     printf ( psz ) ;
        !           150: }
        !           151: 
        !           152: 
        !           153: /***************************************************************************\
        !           154: **                                                                         **
        !           155: **   FUNCTION: DLLInitExitPoint                                            **
        !           156: **                                                                         **
        !           157: **   PURPOSE: Handles both initialization and cleanup of DLL               **
        !           158: **                                                                         **
        !           159: **   INPUT: Handle to module calling this DLL. Flag which indicates        **
        !           160: **          why the DLL entry routine is being called.                     **
        !           161: **                                                                         **
        !           162: **   OUTPUT: None                                                          **
        !           163: **                                                                         **
        !           164: **   ERRORS: Returns FALSE if an error occured while the process was being **
        !           165: **           attached. Any other time the return value is ignored.         **
        !           166: **                                                                         **
        !           167: **   COMMENTS: This function takes place of the LIBMAIN/LIBENTRY and WEP   **
        !           168: **                                                                         **
        !           169: **             Even if no initialization is need this function must return **
        !           170: **                                                                         **
        !           171: **                                                                         **
        !           172: \****************************************************************************/
        !           173: 
        !           174: 
        !           175: 
        !           176: BOOL APIENTRY DLLInitExitPoint ( HANDLE hModule, DWORD dwReason, LPVOID lpReserved )
        !           177: {
        !           178: 
        !           179:     BOOL bSuccess ;
        !           180:     UNREFERENCED_PARAMETER ( hModule ) ;
        !           181:     UNREFERENCED_PARAMETER ( lpReserved ) ;
        !           182: 
        !           183: 
        !           184:     if ( dwReason == DLL_PROCESS_ATTACH ) {
        !           185: 
        !           186:         gUserCount++ ;
        !           187: 
        !           188:         printf ( "\nInitializing subsystem" ) ;
        !           189:         printf ( "\nNumber of clients currently using this are %d\n", gUserCount ) ;
        !           190: 
        !           191:         if ( gUserCount == 1 )
        !           192:             bSuccess = InitializeSubsystem ( ) ;
        !           193:         else
        !           194:             bSuccess = InitApp ( ) ;
        !           195:     }
        !           196: 
        !           197:     else if ( dwReason == DLL_PROCESS_DETACH ) {
        !           198: 
        !           199:         printf ( "\nCleaning up subsystem ...\n" ) ;
        !           200:         printf ( "Number of clients currently using this are %d\n", gUserCount ) ;
        !           201: 
        !           202:         if ( gUserCount ==  1 )
        !           203:             bSuccess = CleanupSubsystem ( ) ;
        !           204:         else
        !           205:             bSuccess = CleanupApp ( ) ;
        !           206: 
        !           207:         gUserCount-- ;
        !           208: 
        !           209:     }
        !           210: 
        !           211: 
        !           212:     return ( bSuccess ) ;
        !           213: }
        !           214: 
        !           215: 
        !           216: /***************************************************************************\
        !           217: **                                                                         **
        !           218: **   FUNCTION: InitializeSubsystem                                         **
        !           219: **                                                                         **
        !           220: **   PURPOSE: Sets up the required synchronization objects to insure both  **
        !           221: **            system performance and data integrity. This is only done     **
        !           222: **            once; by the first process that attaches itself to the DLL   **
        !           223: **                                                                         **
        !           224: **   INPUT: None                                                           **
        !           225: **                                                                         **
        !           226: **   OUTPUT: Returns TRUE if successfull otherwise FALSE                   **
        !           227: **                                                                         **
        !           228: \****************************************************************************/
        !           229: 
        !           230: BOOL InitializeSubsystem ( VOID )
        !           231: {
        !           232:     LONG cSemMax = 5;
        !           233:     BOOL bSuccess ;
        !           234: 
        !           235:     DebugMsg ( "InitializeSubsystem\n" ) ;
        !           236: 
        !           237:     ghSemaphore = CreateSemaphore ( NULL,       // No security descriptor
        !           238: 
        !           239:                                    0,           // Initial count of zero so
        !           240:                                                 // access to database is blocked
        !           241:                                                 // till initialization completed
        !           242:                                    cSemMax,
        !           243:                                                 // Maximun threads allowed to
        !           244:                                                 // access the database at one time
        !           245:                                    SEM1) ;      // No name
        !           246: 
        !           247:     if ( !ghSemaphore )
        !           248:     {
        !           249:         ErrorMsg ( "Error Creating semaphore" ) ;
        !           250:         return ( FALSE ) ;
        !           251:     }
        !           252: 
        !           253: 
        !           254:     ghMutex = CreateMutex ( NULL,               // No security descriptor
        !           255:                             TRUE,               // Block access till database
        !           256:                                                 // is setup
        !           257:                             MUTX1 ) ;           // No name
        !           258:     if ( !ghMutex )
        !           259:     {
        !           260:         ErrorMsg ( "Error Creating Mutex" ) ;
        !           261:         return ( FALSE ) ;
        !           262:     }
        !           263: 
        !           264:     ghReadEvent1 = CreateEvent ( NULL,           // No security descriptor
        !           265:                                 FALSE,          // Use manual reset so all
        !           266:                                                 // waiting threads get signaled
        !           267:                                 FALSE,          // Set to non-signaled state
        !           268:                                 EVENT1 ) ;
        !           269: 
        !           270: 
        !           271:     if ( !ghReadEvent1 )
        !           272:     {
        !           273:         ErrorMsg ( "Error Creating ghReadEvent1" ) ;
        !           274:         return ( FALSE ) ;
        !           275:     }
        !           276: 
        !           277:     ghWriteEvent1 = CreateEvent ( NULL,           // No security descriptor
        !           278:                                 FALSE,          // Use manual reset so all
        !           279:                                                 // waiting threads get signaled
        !           280:                                 FALSE,          // Set to non-signaled state
        !           281:                                 EVENT2 ) ;
        !           282: 
        !           283: 
        !           284:     if ( !ghWriteEvent1 )
        !           285:     {
        !           286:         ErrorMsg ( "Error Creating ghWriteEvent1" ) ;
        !           287:         return ( FALSE ) ;
        !           288:     }
        !           289: 
        !           290:     ghReadEvent2 = CreateEvent ( NULL,           // No security descriptor
        !           291:                                 FALSE,          // Use manual reset so all
        !           292:                                                 // waiting threads get signaled
        !           293:                                 FALSE,          // Set to non-signaled state
        !           294:                                 EVENT3 ) ;
        !           295: 
        !           296: 
        !           297:     if ( !ghReadEvent2 )
        !           298:     {
        !           299:         ErrorMsg ( "Error Creating ghReadEvent2" ) ;
        !           300:         return ( FALSE ) ;
        !           301:     }
        !           302: 
        !           303:     ghWriteEvent2 = CreateEvent ( NULL,           // No security descriptor
        !           304:                                 FALSE,          // Use manual reset so all
        !           305:                                                 // waiting threads get signaled
        !           306:                                 FALSE,          // Set to non-signaled state
        !           307:                                 EVENT4 ) ;
        !           308: 
        !           309:     if ( !ghWriteEvent2 )
        !           310:     {
        !           311:         ErrorMsg ( "Error Creating ghWriteEvent2" ) ;
        !           312:         return ( FALSE ) ;
        !           313:     }
        !           314: 
        !           315:     bSuccess = InitializeDataBase () ;
        !           316: 
        !           317: 
        !           318:     /*
        !           319:      * Now that all the initialization is done it's save to
        !           320:      * release the semaphore and mutex.
        !           321:      *
        !           322:      */
        !           323: 
        !           324:     if ( !ReleaseSemaphore ( ghSemaphore,       // Handle to semaphore
        !           325:                        cSemMax,                 // Size to increment
        !           326:                        NULL ) )                 // Don't care about previous value
        !           327:         {
        !           328:             ErrorMsg ( "Error releasing semaphore" ) ;
        !           329:             return ( FALSE ) ;
        !           330:         }
        !           331: 
        !           332: 
        !           333:     if ( !ReleaseMutex ( ghMutex ) )            // Handle to semaphore
        !           334:         {
        !           335:             ErrorMsg ( "Error releasing mutex" ) ;
        !           336:             return ( FALSE ) ;
        !           337:         }
        !           338: 
        !           339:     return ( bSuccess ) ;
        !           340: }
        !           341: 
        !           342: /***************************************************************************\
        !           343: **                                                                         **
        !           344: **   FUNCTION: InitApp                                                     **
        !           345: **                                                                         **
        !           346: **   PURPOSE: Sets up the required synchronization objects to insure both  **
        !           347: **            system performance and data integrity. This is done each     **
        !           348: **            a process attaches itself to this DLL                        **
        !           349: **                                                                         **
        !           350: **   INPUT: None                                                           **
        !           351: **                                                                         **
        !           352: **   OUTPUT: Returns TRUE if successfull otherwise FALSE                   **
        !           353: **                                                                         **
        !           354: \****************************************************************************/
        !           355: 
        !           356: BOOL InitApp ( VOID )
        !           357: {
        !           358: 
        !           359:     DebugMsg ( "InitApp\n" ) ;
        !           360: 
        !           361:     ghSemaphore = OpenSemaphore ( SEMAPHORE_ALL_ACCESS,  //
        !           362:                                  FALSE,                  // No inheritance
        !           363:                                  SEM1 ) ;                // No name
        !           364: 
        !           365:     if ( !ghSemaphore )
        !           366:     {
        !           367:         ErrorMsg ( "Error Opening semaphore" ) ;
        !           368:         return ( FALSE ) ;
        !           369:     }
        !           370: 
        !           371: 
        !           372:     ghMutex = OpenMutex  ( MUTEX_ALL_ACCESS,    //
        !           373:                            FALSE,               // No inheritance
        !           374:                            MUTX1 ) ;            // No name
        !           375:     if ( !ghMutex )
        !           376:     {
        !           377:         ErrorMsg ( "Error Opening Mutex" ) ;
        !           378:         return ( FALSE ) ;
        !           379:     }
        !           380: 
        !           381:     ghReadEvent1 = OpenEvent ( EVENT_ALL_ACCESS, //
        !           382:                               FALSE,            // No inheritance
        !           383:                               EVENT1 ) ;        //
        !           384: 
        !           385:     if ( !ghReadEvent1 )
        !           386:     {
        !           387:         ErrorMsg ( "Error Opening ghReadEvent1" ) ;
        !           388:         return ( FALSE ) ;
        !           389:     }
        !           390: 
        !           391: 
        !           392:     ghWriteEvent1 = OpenEvent ( EVENT_ALL_ACCESS, //
        !           393:                                FALSE,            // No inheritance
        !           394:                                EVENT2 ) ;        //
        !           395: 
        !           396: 
        !           397:     if ( !ghWriteEvent1 )
        !           398:     {
        !           399:         ErrorMsg ( "Error Opening ghWriteEvent1" ) ;
        !           400:         return ( FALSE ) ;
        !           401:     }
        !           402: 
        !           403:     ghReadEvent2 = OpenEvent ( EVENT_ALL_ACCESS, //
        !           404:                               FALSE,            // No inheritance
        !           405:                               EVENT3 ) ;        //
        !           406: 
        !           407:     if ( !ghReadEvent2 )
        !           408:     {
        !           409:         ErrorMsg ( "Error Opening ghReadEvent2" ) ;
        !           410:         return ( FALSE ) ;
        !           411:     }
        !           412: 
        !           413: 
        !           414:     ghWriteEvent2 = OpenEvent ( EVENT_ALL_ACCESS, //
        !           415:                                FALSE,            // No inheritance
        !           416:                                EVENT4 ) ;        //
        !           417: 
        !           418: 
        !           419:     if ( !ghWriteEvent2 )
        !           420:     {
        !           421:         ErrorMsg ( "Error Opening ghWriteEvent2" ) ;
        !           422:         return ( FALSE ) ;
        !           423:     }
        !           424: 
        !           425:     return ( TRUE ) ;
        !           426: }
        !           427: 
        !           428: 
        !           429: 
        !           430: BOOL CleanupSubsystem ( VOID )
        !           431: {
        !           432:     DebugMsg ( "CleanupSubsystem\n" ) ;
        !           433: 
        !           434:     if ( !CloseHandle ( ghSemaphore ) )
        !           435:         ErrorMsg ( "Error Closing Semaphore" ) ;
        !           436: 
        !           437:     if ( !CloseHandle ( ghMutex ) )
        !           438:         ErrorMsg ( "Error Closing Mutex" ) ;
        !           439: 
        !           440:     if ( !CloseHandle ( ghReadEvent1 ) )
        !           441:         ErrorMsg ( "Error Closing Event" ) ;
        !           442: 
        !           443:     if ( !CloseHandle ( ghWriteEvent1 ) )
        !           444:         ErrorMsg ( "Error Closing Event" ) ;
        !           445: 
        !           446:     CloseDataBase ( ) ;
        !           447: 
        !           448:     return ( TRUE ) ;
        !           449: }
        !           450: 
        !           451: 
        !           452: /***************************************************************************\
        !           453: **                                                                         **
        !           454: **   FUNCTION: CleanupApp                                                  **
        !           455: **                                                                         **
        !           456: **   PURPOSE: Cleans up (closes) the synchronization objects.              **
        !           457: **            This is done each a process attaches itself to this DLL      **
        !           458: **                                                                         **
        !           459: **   INPUT: None                                                           **
        !           460: **                                                                         **
        !           461: **   OUTPUT: Returns TRUE if successfull otherwise FALSE                   **
        !           462: **                                                                         **
        !           463: \****************************************************************************/
        !           464: 
        !           465: BOOL CleanupApp ( VOID )
        !           466: {
        !           467:     DebugMsg ( "CleanupApp\n" ) ;
        !           468: 
        !           469:     if ( !CloseHandle ( ghSemaphore ) )
        !           470:         ErrorMsg ( "Error Closing Semaphore" ) ;
        !           471: 
        !           472:     if ( !CloseHandle ( ghMutex ) )
        !           473:         ErrorMsg ( "Error Closing Mutex" ) ;
        !           474: 
        !           475:     if ( !CloseHandle ( ghReadEvent1 ) )
        !           476:         ErrorMsg ( "Error Closing Event" ) ;
        !           477: 
        !           478:     if ( !CloseHandle ( ghWriteEvent1 ) )
        !           479:         ErrorMsg ( "Error Closing Event" ) ;
        !           480: 
        !           481:     return ( TRUE ) ;
        !           482: }
        !           483: 
        !           484: 
        !           485: /***************************************************************************\
        !           486: **                                                                         **
        !           487: **   FUNCTION: InitializeDataBase                                          **
        !           488: **                                                                         **
        !           489: **   PURPOSE:
        !           490: **
        !           491: **                                                                         **
        !           492: **   INPUT: None                                                           **
        !           493: **                                                                         **
        !           494: **   OUTPUT: Returns TRUE if successfull otherwise FALSE                   **
        !           495: **                                                                         **
        !           496: \****************************************************************************/
        !           497: 
        !           498: BOOL InitializeDataBase ( VOID )
        !           499: {
        !           500:     UINT i ;
        !           501: 
        !           502:     DebugMsg ( "Initializing database\n" ) ;
        !           503: 
        !           504:     for ( i=0; i< MAX; i++ )
        !           505:         PutData ( "Unintialized" ) ;
        !           506: 
        !           507:     return ( TRUE ) ;
        !           508: }
        !           509: 
        !           510: 
        !           511: /***************************************************************************\
        !           512: **                                                                         **
        !           513: **   FUNCTION: CloseDataBase                                               **
        !           514: **                                                                         **
        !           515: **   PURPOSE:
        !           516: **
        !           517: **                                                                         **
        !           518: **   INPUT: None                                                           **
        !           519: **                                                                         **
        !           520: **   OUTPUT: Returns TRUE if successfull otherwise FALSE                   **
        !           521: **                                                                         **
        !           522: \****************************************************************************/
        !           523: 
        !           524: BOOL CloseDataBase ( VOID )
        !           525: {
        !           526:     DebugMsg ( "Closing database\n" ) ;
        !           527:     return ( TRUE ) ;
        !           528: }
        !           529: 
        !           530: 
        !           531: /***************************************************************************\
        !           532: **                                                                         **
        !           533: **   FUNCTION: ReadDataBase ( PSZ                                          **
        !           534: **                                                                         **
        !           535: **   PURPOSE: Fetches data out of the database                             **
        !           536: **                                                                         **
        !           537: **   INPUT: None                                                           **
        !           538: **                                                                         **
        !           539: **   OUTPUT: Pointer to data                                               **
        !           540: **                                                                         **
        !           541: **   ERROR: Returns False if it can not complete the request               **
        !           542: **                                                                         **
        !           543: **   COMMENTS:  A reader can not enter the database if                     **
        !           544: **                                                                         **
        !           545: **              1) A writer already is in the database                     **
        !           546: **              2) The maximum number of readers are in the database       **
        !           547: **                                                                         **
        !           548: **              A new reader can not enter the databse if                  **
        !           549: **                                                                         **
        !           550: **              1) A writer is waiting                                     **
        !           551: **                                                                         **
        !           552: \****************************************************************************/
        !           553: 
        !           554: 
        !           555: BOOL APIENTRY ReadDataBase  ( PSZ psz1, PSZ psz2 )
        !           556: {
        !           557:    BOOL bSuccess ;
        !           558:    DWORD dwSuccess ;
        !           559:    UNREFERENCED_PARAMETER ( psz2 ) ;
        !           560: 
        !           561: //   DebugMsg ("In ReadDataBase\n" ) ;
        !           562: 
        !           563:    cReadQueueEx++ ;
        !           564:    dwSuccess = SIGNALED ;
        !           565: 
        !           566:    if ( cWriteQueue )                              // Block if Writer waiting
        !           567:          dwSuccess = WaitForSingleObject ( ghReadEvent1, 0xFFFFFFFF ) ;
        !           568: //       dwSuccess = WaitForSingleObject ( ghReadEvent1, 5000 ) ;
        !           569: 
        !           570:    cReadQueue++ ;                                   // Reader entering queue
        !           571:    cReadQueueEx-- ;
        !           572: 
        !           573:    if ( dwSuccess != SIGNALED )
        !           574:    {
        !           575:       ErrorMsg ( "ReadDatabase: Error Waiting for ghReadEvent1" ) ;
        !           576:       bSuccess = FALSE ;
        !           577:    }
        !           578:    else
        !           579:    {
        !           580:    /*
        !           581:     * Only let N readers in the queue at one time
        !           582:     */
        !           583:       switch ( WaitForSingleObject ( ghSemaphore, 0xFFFFFFFF ) )
        !           584: //      switch ( WaitForSingleObject ( ghSemaphore, 3000 ) )
        !           585:       {
        !           586:          case SIGNALED:
        !           587:              try {
        !           588:                   if ( InWrite )               // Block if Writer in database
        !           589:                      dwSuccess = WaitForSingleObject ( ghReadEvent2, 0xFFFFFFFF ) ;
        !           590: //                   dwSuccess = WaitForSingleObject ( ghReadEvent2, 1500 ) ;
        !           591: 
        !           592:                   cRead++ ;                    // Number readers in database
        !           593:                    cReadQueue-- ;              // Reader leaving queue
        !           594: 
        !           595:                    /*
        !           596:                     * Signal Writer if no Reader waiting
        !           597:                     *
        !           598:                     */
        !           599:                    if ( !cReadQueue )
        !           600:                       bSuccess = SetEvent ( ghWriteEvent1 ) ;
        !           601: 
        !           602:                   if ( dwSuccess == SIGNALED )
        !           603:                   {
        !           604:                      bSuccess = GetData ( psz1 ) ;   // Read data
        !           605:                      cRead-- ;
        !           606:                       /*
        !           607:                        * Signal Writer if no Reader in database
        !           608:                        *
        !           609:                        */
        !           610: 
        !           611:                       if ( !cRead )
        !           612:                          bSuccess = SetEvent ( ghWriteEvent2 ) ;
        !           613: 
        !           614:                      ReleaseSemaphore ( ghSemaphore, // Let next waiting
        !           615:                                          1,          // reader in the queue
        !           616:                                          NULL ) ;
        !           617:                   }
        !           618:                   else
        !           619:                   {
        !           620:                      cRead-- ;
        !           621:                       /*
        !           622:                        * Signal Writer if no Reader in database
        !           623:                        *
        !           624:                        */
        !           625: 
        !           626:                       if ( !cRead )
        !           627:                          bSuccess = SetEvent ( ghWriteEvent2 ) ;
        !           628: 
        !           629:                      bSuccess = FALSE ;
        !           630:                      DebugMsg ( "ReadDataBase: Error Waiting for ghReadEvent2\n" ) ;
        !           631:                   }
        !           632:              }
        !           633:              finally {
        !           634:                  // what if these is already decremented above????
        !           635:                    cRead-- ;
        !           636:                    /*
        !           637:                     * Signal Writer if no Reader in database
        !           638:                     *
        !           639:                     */
        !           640: 
        !           641:                    if ( !cRead )
        !           642:                       bSuccess = SetEvent ( ghWriteEvent2 ) ;
        !           643: 
        !           644:                    /*
        !           645:                     * Signal Writer if no Reader in queue
        !           646:                     *
        !           647:                     */
        !           648:                    if ( !cReadQueue )
        !           649:                       bSuccess = SetEvent ( ghWriteEvent1 ) ;
        !           650: 
        !           651:                   bSuccess = FALSE ;
        !           652:                   ReleaseSemaphore ( ghSemaphore,     // Let next waiting
        !           653:                                  1,                   // reader in the queue
        !           654:                                  NULL ) ;
        !           655:              }
        !           656: 
        !           657:              break ;
        !           658: 
        !           659:          case WAIT_TIMEOUT:
        !           660:              DebugMsg ( "ReadDataBase: Error WAIT_TIMEOUT ghSemaphore\n" ) ;
        !           661: 
        !           662:               //where to put this?
        !           663:               cReadQueue-- ;           // Reader leaving queue
        !           664:               /*
        !           665:                * Signal Writer if no Reader waiting
        !           666:                *
        !           667:                */
        !           668:               if ( !cReadQueue )
        !           669:                  bSuccess = SetEvent ( ghWriteEvent1 ) ;
        !           670: 
        !           671:              bSuccess = FALSE ;
        !           672:              break ;
        !           673: 
        !           674:          case WAIT_ERROR:
        !           675:              ErrorMsg ( "ReadDataBase: Error WAIT_ERROR ghSemaphore" ) ;
        !           676: 
        !           677:               //where to put this?
        !           678:               cReadQueue-- ;           // Reader leaving queue
        !           679:               /*
        !           680:                * Signal Writer if no Reader waiting
        !           681:                *
        !           682:                */
        !           683:               if ( !cReadQueue )
        !           684:                  bSuccess = SetEvent ( ghWriteEvent1 ) ;
        !           685: 
        !           686:              bSuccess = FALSE ;
        !           687:              break ;
        !           688: 
        !           689:          default:
        !           690:              DebugMsg ( "ReadDataBase: Dropped through switch\n" ) ;
        !           691: 
        !           692:               //where to put this?
        !           693:               cReadQueue-- ;           // Reader leaving queue
        !           694:               /*
        !           695:                * Signal Writer if no Reader waiting
        !           696:                *
        !           697:                */
        !           698:               if ( !cReadQueue )
        !           699:                  bSuccess = SetEvent ( ghWriteEvent1 ) ;
        !           700: 
        !           701:              bSuccess = FALSE ;
        !           702:              break ;
        !           703:       }
        !           704:    } // END IF
        !           705: 
        !           706: 
        !           707: 
        !           708:    return ( bSuccess ) ;
        !           709: }
        !           710: 
        !           711: 
        !           712: 
        !           713: 
        !           714: 
        !           715: /***************************************************************************\
        !           716: **                                                                         **
        !           717: **   FUNCTION: WriteDataBase ( PSZ                                         **
        !           718: **                                                                         **
        !           719: **   PURPOSE: Puts data into the database                                  **
        !           720: **                                                                         **
        !           721: **   INPUT: Pointer to data                                                **
        !           722: **                                                                         **
        !           723: **   OUTPUT: None                                                          **
        !           724: **                                                                         **
        !           725: **   ERROR: Returns False if it can not complete the request               **
        !           726: **                                                                         **
        !           727: **   COMMENTS:  A writer can not enter the database if                     **
        !           728: **                                                                         **
        !           729: **              1) A writer already is in the database                     **
        !           730: **              2) Any readers are in the database                         **
        !           731: **                                                                         **
        !           732: **              All reader waiting at the end of a write operation         **
        !           733: **              have priority over the next writer                         **
        !           734: **                                                                         **
        !           735: \****************************************************************************/
        !           736: 
        !           737: BOOL APIENTRY WriteDataBase ( PSZ psz1, PSZ psz2 )
        !           738: {
        !           739:    BOOL bSuccess ;
        !           740:    DWORD dwSuccess ;
        !           741:    UNREFERENCED_PARAMETER ( psz2 ) ;
        !           742: 
        !           743: //   DebugMsg ( "In WriteDataBase\n" ) ;
        !           744: 
        !           745:    cWriteQueue++ ;                            // Writer entering queue
        !           746:    dwSuccess = SIGNALED ;
        !           747: 
        !           748:                   // should the same event be used twice ???
        !           749: 
        !           750:    if ( cReadQueue )                          // Block if Reader waiting
        !           751:       dwSuccess = WaitForSingleObject ( ghWriteEvent1, 0xFFFFFFFF ) ;
        !           752: //      dwSuccess = WaitForSingleObject ( ghWriteEvent1, 5000 ) ;
        !           753: 
        !           754:    if ( dwSuccess != SIGNALED )
        !           755:    {
        !           756:       DebugMsg ( "WriteDataBase: Error Waiting for ghWriteEvent1\n" ) ;
        !           757:       bSuccess = FALSE ;
        !           758:    }
        !           759:    else
        !           760:    {
        !           761:    /*
        !           762:     * Only allow 1 writer at a time in the database
        !           763:     *
        !           764:     */
        !           765:       switch ( WaitForSingleObject ( ghMutex, 0xFFFFFFFF ) ) {
        !           766: //      switch ( WaitForSingleObject ( ghMutex, 3000 ) ) {
        !           767:         case SIGNALED:
        !           768:            try {
        !           769:               InWrite = TRUE ;
        !           770:                cWriteQueue-- ;
        !           771: 
        !           772:                /*
        !           773:                 * Signal Reader if any waiting
        !           774:                 *
        !           775:                 */
        !           776:                if ( cReadQueueEx )
        !           777:                   bSuccess = SetEvent ( ghReadEvent1 ) ;
        !           778: 
        !           779:                                       // Writer leaving queue
        !           780:               if ( cRead )               // Block if Reader in database
        !           781:                  dwSuccess = WaitForSingleObject ( ghWriteEvent2, 0xFFFFFFFF ) ;
        !           782: //               dwSuccess = WaitForSingleObject ( ghWriteEvent2, 1500 ) ;
        !           783: 
        !           784:               if ( dwSuccess == SIGNALED )
        !           785:               {
        !           786:                  bSuccess = PutData ( psz1 ) ;
        !           787:                  InWrite = FALSE ;
        !           788:                   /*
        !           789:                    * Signal Reader when no Writer waiting
        !           790:                    *
        !           791:                    */
        !           792:                   bSuccess = SetEvent ( ghReadEvent2 ) ;
        !           793:                  ReleaseMutex ( ghMutex ) ;    // Let next waiting writer in the queue
        !           794:               }
        !           795:                else
        !           796:                {
        !           797:                   bSuccess = FALSE ;
        !           798:                   InWrite = FALSE ;
        !           799:                   /*
        !           800:                    * Signal Reader when no Writer waiting
        !           801:                    *
        !           802:                    */
        !           803:                   bSuccess = SetEvent ( ghReadEvent2 ) ;
        !           804:                   DebugMsg ( "WriteDataBase: Error Waiting on ghWriteEvent2\n" ) ;
        !           805:                }
        !           806:            }
        !           807:            finally {
        !           808:               InWrite = FALSE ;
        !           809:                /*
        !           810:                 * Signal Reader after leaving database
        !           811:                 *
        !           812:                 */
        !           813:                bSuccess = SetEvent ( ghReadEvent2 ) ;
        !           814: 
        !           815:                /*
        !           816:                 * Signal Reader if no Writer in queue
        !           817:                 *
        !           818:                 */
        !           819:                if ( !cWriteQueue )
        !           820:                   bSuccess = SetEvent ( ghReadEvent1 ) ;
        !           821: 
        !           822:                bSuccess = FALSE ;
        !           823:               ReleaseMutex ( ghMutex ) ;
        !           824:            }
        !           825:            break ;
        !           826: 
        !           827:         case WAIT_TIMEOUT:
        !           828:            DebugMsg ( "WriteDataBase: Error WAIT_TIMEOUT ghMutex\n" ) ;
        !           829:             cWriteQueue-- ;
        !           830:             /*
        !           831:              * Signal Reader if no Writer waiting
        !           832:              *
        !           833:              */
        !           834:             if ( !cWriteQueue )
        !           835:                bSuccess = SetEvent ( ghReadEvent1 ) ;
        !           836: 
        !           837:            bSuccess = FALSE ;
        !           838:            break ;
        !           839: 
        !           840:         case WAIT_ABANDONED:
        !           841:            DebugMsg ( "WriteDataBase: Error WAIT_ABANDONED ghMutex\n" ) ;
        !           842:             cWriteQueue-- ;
        !           843:             /*
        !           844:              * Signal Reader if no Writer waiting
        !           845:              *
        !           846:              */
        !           847:             if ( !cWriteQueue )
        !           848:                bSuccess = SetEvent ( ghReadEvent1 ) ;
        !           849: 
        !           850:            bSuccess = FALSE ;
        !           851:            break ;
        !           852: 
        !           853:         case WAIT_ERROR:
        !           854:            ErrorMsg ( "WriteDataBase: Error WAIT_ERROR ghMutex" ) ;
        !           855:             cWriteQueue-- ;
        !           856:             /*
        !           857:              * Signal Reader if no Writer waiting
        !           858:              *
        !           859:              */
        !           860:             if ( !cWriteQueue )
        !           861:                bSuccess = SetEvent ( ghReadEvent1 ) ;
        !           862: 
        !           863:            bSuccess = FALSE ;
        !           864:            break ;
        !           865: 
        !           866:         default:
        !           867:            DebugMsg ( "WriteDataBase: Dropped through switch\n" ) ;
        !           868:             cWriteQueue-- ;
        !           869:             /*
        !           870:              * Signal Reader if no Writer waiting
        !           871:              *
        !           872:              */
        !           873:             if ( !cWriteQueue )
        !           874:                bSuccess = SetEvent ( ghReadEvent1 ) ;
        !           875: 
        !           876:            bSuccess = FALSE ;
        !           877:            break ;
        !           878:       }
        !           879:    } // END IF
        !           880: 
        !           881: 
        !           882:    if ( cReadQueue )
        !           883:        bSuccess = SetEvent ( ghReadEvent1 ) ;         // Signal Reader
        !           884:    else
        !           885:        bSuccess = SetEvent ( ghWriteEvent1 ) ;        // Signal Writer
        !           886: 
        !           887:    return ( bSuccess ) ;
        !           888: }
        !           889: 
        !           890: 
        !           891: 
        !           892: BOOL GetData ( PSZ psz )
        !           893: {
        !           894:     static UINT i = 0 ;
        !           895: 
        !           896:     strcpy ( psz, DataBase[i++ % MAX] ) ;
        !           897:     return ( TRUE ) ;
        !           898: }
        !           899: 
        !           900: 
        !           901: BOOL PutData ( PSZ psz )
        !           902: {
        !           903:     static UINT i = 0 ;
        !           904: 
        !           905:     i++ ;
        !           906:     DataBase[i % MAX] = strdup ( psz ) ;
        !           907:     return ( TRUE ) ;
        !           908: }

unix.superglobalmegacorp.com

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