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

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

unix.superglobalmegacorp.com

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