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

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

unix.superglobalmegacorp.com

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