Annotation of q_a/samples/mutex/mutex.c, revision 1.1

1.1     ! root        1: /*************************************************************************\
        !             2: *  PROGRAM: Mutex.c
        !             3: *
        !             4: *  PURPOSE:
        !             5: *
        !             6: *    To demonstrate the use of a named mutex between processes.
        !             7: *
        !             8: *  GLOBAL VARIABLES:
        !             9: *
        !            10: *    HANDLE hInst;  - Instance handle.
        !            11: *
        !            12: *    HWND   hWnd;   - Client window handle.
        !            13: *
        !            14: *    CHAR Buf[80], Buf2[80];
        !            15: *           Error message buffers.
        !            16: *
        !            17: *  FUNCTIONS:
        !            18: *
        !            19: *    WinMain()      - Initializes the window, and process the message loop.
        !            20: *    MainWndProc()  - To handle the messages to the main window.
        !            21: *    RequestProc()  - Prints a message when it gets access to the mutex.
        !            22: *
        !            23: *  COMMENTS:
        !            24: *
        !            25: *    Overview:
        !            26: *      Between processes it is better to use a mutex than a semaphore
        !            27: *      to control access to a mutual resourse.  A serious draw back
        !            28: *      to a semaphore is that any thread can call ReleaseSemaphore
        !            29: *      and change its usage count (or access).  Another drawback is that
        !            30: *      if a thread or process dies before calling ReleaseSemaphore, than
        !            31: *      no other process or thread will be able to access it (because the
        !            32: *      use count hasn't been updated).  When a process controlling
        !            33: *      a mutex dies, the mutex is freed for other processes.
        !            34: *
        !            35: *    To Use:
        !            36: *      Start any number of instances of this application.  Each instance
        !            37: *      will start a thread which will request access to the mutex.
        !            38: *      when the thread has the mutex, it will print a message in the
        !            39: *      application window "I HAVE CONTROL OF THE MUTEX!", and then
        !            40: *      sleep for two seconds.  It will then wakeup, erase the message,
        !            41: *      release the mutex; and then sleep for another two seconds before
        !            42: *      asking for control again.  By starting several instances, you will
        !            43: *      see that each instance will often have to wait longer than its two
        !            44: *      seconds before it gets control.
        !            45: *
        !            46: \*************************************************************************/
        !            47: 
        !            48: #include <windows.h>
        !            49: #include <stdlib.h>
        !            50: #include <stdio.h>
        !            51: #include "mutex.h"
        !            52: 
        !            53:                             // used for error messages.
        !            54: #define WERR(who,where)    {sprintf(Buf,"ERROR: %s returned %u, line: %u", who, GetLastError(), __LINE__);\
        !            55:                             sprintf(Buf2,"From within %s", where);\
        !            56:                             MessageBox(hWnd, Buf, Buf2, MB_OK);}
        !            57: 
        !            58: 
        !            59: CHAR Buf[80];
        !            60: CHAR Buf2[80];
        !            61: HANDLE hInst;
        !            62: HWND   hWnd;
        !            63: 
        !            64: 
        !            65: 
        !            66: 
        !            67: /*************************************************************************\
        !            68: *
        !            69: *  FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
        !            70: *
        !            71: *  PURPOSE:  Calls initialization function, processes message loop.
        !            72: *
        !            73: *  COMMENTS: A fairly standard WinMain.
        !            74: *
        !            75: \*************************************************************************/
        !            76: 
        !            77: int APIENTRY WinMain (HANDLE hInstance,
        !            78:                       HANDLE hPrevInstance,
        !            79:                       LPSTR  lpCmdLine,
        !            80:                       int    nCmdShow)
        !            81: 
        !            82: 
        !            83: {
        !            84: 
        !            85:   MSG  msg;
        !            86:   WNDCLASS wc;
        !            87: 
        !            88:   UNREFERENCED_PARAMETER( lpCmdLine );
        !            89:   UNREFERENCED_PARAMETER( hPrevInstance );
        !            90: 
        !            91:   hInst = hInstance;
        !            92: 
        !            93:   wc.style = NULL;                       // Replaces CS_SIZEREDRAW.
        !            94:   wc.lpfnWndProc = (WNDPROC)MainWndProc; // The client window procedure.
        !            95:   wc.cbClsExtra = 0;                     // No room reserved for extra data.
        !            96:   wc.cbWndExtra = 0;
        !            97:   wc.hInstance = hInstance;
        !            98:   wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        !            99:   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
        !           100:   wc.hbrBackground = GetStockObject (WHITE_BRUSH);
        !           101:   wc.lpszMenuName = "";
        !           102:   wc.lpszClassName = "MutexWClass";
        !           103: 
        !           104:   RegisterClass(&wc);
        !           105: 
        !           106:   hWnd = CreateWindow ("MutexWClass",
        !           107:                        "Mutex Between Processes Sample",
        !           108:                        WS_OVERLAPPEDWINDOW,
        !           109:                        CW_USEDEFAULT,
        !           110:                        CW_USEDEFAULT,
        !           111:                        CW_USEDEFAULT,
        !           112:                        CW_USEDEFAULT,
        !           113:                        NULL,
        !           114:                        NULL,
        !           115:                        hInstance,
        !           116:                        NULL);
        !           117: 
        !           118: 
        !           119:   ShowWindow  (hWnd, nCmdShow);
        !           120: 
        !           121:   while (GetMessage (&msg, NULL, NULL, NULL))
        !           122:        DispatchMessage (&msg);   // Dispatch message to window.
        !           123: 
        !           124:   return (msg.wParam);           // Returns value from PostQuitMessage.
        !           125: 
        !           126: }
        !           127: 
        !           128: /*************************************************************************\
        !           129: *
        !           130: *  FUNCTION:  MainWndProc (HWND, UINT, UINT, LONG)
        !           131: *
        !           132: *  PURPOSE:   To process messages.  To launch client and server threads
        !           133: *             as appropriate.
        !           134: *
        !           135: *
        !           136: *  MESSAGES:
        !           137: *
        !           138: *    WM_CREATE       - Creates a thread.
        !           139: *
        !           140: *    WM_DESTROY      - Standard, destroys the window.
        !           141: *
        !           142: *  CALLED BY:
        !           143: *
        !           144: *    WinMain();
        !           145: *
        !           146: *  CALLS TO:
        !           147: *
        !           148: *    RequestProc()   - The thread procedure.
        !           149: *
        !           150: \*************************************************************************/
        !           151: 
        !           152: LONG APIENTRY MainWndProc (HWND hwnd,
        !           153:                            UINT message,
        !           154:                            UINT wParam,
        !           155:                            LONG lParam)
        !           156: {
        !           157:   DWORD    ThreadID;
        !           158:   HANDLE   hThread;
        !           159: 
        !           160:   switch (message)
        !           161:       {
        !           162: 
        !           163:         case WM_CREATE:
        !           164: 
        !           165:           hThread = CreateThread (NULL, 0,
        !           166:                                   (LPTHREAD_START_ROUTINE)RequestProc,
        !           167:                                   (LPVOID)NULL, NULL,
        !           168:                                   (LPDWORD)&ThreadID);
        !           169:           if (!hThread)
        !           170:             WERR("CreateThread", "WM_CREATE");
        !           171:           CloseHandle (hThread);
        !           172:           return (0);
        !           173: 
        !           174: 
        !           175:         case WM_DESTROY :
        !           176:           PostQuitMessage (0);
        !           177:           return (0);
        !           178:        }
        !           179:   return DefWindowProc (hwnd, message, wParam, lParam);
        !           180: }
        !           181: 
        !           182: 
        !           183: /*************************************************************************\
        !           184: *
        !           185: *  FUNCTION:  VOID RequestProc (VOID)
        !           186: *
        !           187: *  PURPOSE:   This thread tries to create the Mutex.  Only the first thread
        !           188: *             created will succeed, all others will fail.  Then this thread
        !           189: *             tries to open the mutex.  If successful, it
        !           190: *             enters a loop.  The loop asks for control of the mutex.
        !           191: *             Once it has control, it prints the message in the application
        !           192: *             window, and sleeps for two seconds.  It then releases
        !           193: *             the mutex, erases the message, and sleeps another two
        !           194: *             seconds before trying to get control again.
        !           195: *
        !           196: *  VARIABLES USED:
        !           197: *
        !           198: *    - hMutex:
        !           199: *             A handle to the mutex.
        !           200: *
        !           201: *    - rect, textRect:
        !           202: *             RECT structures.  One for the client area, one for the
        !           203: *             text location.
        !           204: *
        !           205: *    - hDC:   The DC of the window.
        !           206: *
        !           207: *    - X, Y:  Integers/coordinates used to locate the text
        !           208: *
        !           209: *    - hBrush:
        !           210: *             Handle to a brush, used to erase the old text.
        !           211: *
        !           212: *    - size:  A SIZE struct, used to determin the size of the font
        !           213: *             and message on the window.
        !           214: *
        !           215: *
        !           216: \*************************************************************************/
        !           217: VOID RequestProc(VOID)
        !           218: {
        !           219:   HANDLE hMutex;
        !           220:   RECT   rect, textRect;
        !           221:   HDC    hDC;
        !           222:   LONG   X, Y;
        !           223:   SIZE   size;
        !           224:   DWORD  retCode;
        !           225: 
        !           226: 
        !           227: 
        !           228:   hMutex = CreateMutex (NULL, FALSE, "my_mutex");
        !           229:    if (!hMutex)
        !           230:      {
        !           231:      retCode = GetLastError();
        !           232:      if (retCode != ERROR_ALREADY_EXISTS)
        !           233:        {
        !           234:        SetLastError(retCode);
        !           235:        WERR("CreateMutex", "WM_CREATE");
        !           236:        PostQuitMessage(0);
        !           237:        }
        !           238:      }
        !           239: 
        !           240:   hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "my_mutex");
        !           241:   if (!hMutex)
        !           242:      {
        !           243:      WERR("OpenMutex", "From RequestProc");
        !           244:      return;
        !           245:      }
        !           246: 
        !           247:   hDC = GetDC (hWnd);
        !           248:   GetTextExtentPoint (hDC, "I HAVE CONTROL OF THE MUTEX!", 28, &size);
        !           249:   ReleaseDC (hWnd, hDC);
        !           250: 
        !           251:   while(!IsWindow(hWnd));
        !           252: 
        !           253:   while(1)
        !           254:     {
        !           255:      WaitForSingleObject (hMutex, INFINITE);
        !           256: 
        !           257:      hDC = GetDC (hWnd);
        !           258:      GetClientRect (hWnd, &rect);
        !           259:      X = ((rect.right - rect.left) / 2) - (size.cx / 2);
        !           260:      Y = (rect.bottom - rect.top) / 2;
        !           261: 
        !           262:      TextOut (hDC, X, Y, "I HAVE CONTROL OF THE MUTEX!", 28);
        !           263: 
        !           264:      MessageBeep (0);              // Forces a flush of the window buffers.
        !           265:      Sleep(2000);
        !           266: 
        !           267:      textRect.left   = X,
        !           268:      textRect.right  = X + size.cx;
        !           269:      textRect.top    = Y;
        !           270:      textRect.bottom = Y + size.cy;
        !           271:      FillRect (hDC, &textRect, GetStockObject(WHITE_BRUSH));
        !           272: 
        !           273:      ReleaseDC(hWnd, hDC);
        !           274:      ReleaseMutex (hMutex);
        !           275:      Sleep(2000);
        !           276:     }
        !           277: }

unix.superglobalmegacorp.com

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