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

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

unix.superglobalmegacorp.com

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