Annotation of q_a/samples/mutex/mutex.c, revision 1.1.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.