Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Interprocess signaling with Mutex

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Interprocess signaling with Mutex

    While looking into communication between processes, I wrote the routine SetMutex()
    which is quite simple but very effective, and I thought it is worth sharing ...

    The routine can be used to signal the execution of a command, routine or process
    which then may be monitored by any other process.

    The demo program lets you create and monitor lots of named Mutexes.
    At start it launches a second instances but additional ones can be loaded at any time.

    Keep in mind that a Mutex can only be destroyed in the program where it was created
    - by CloseHandle() or by terminating the program.
    In this demo the BackSpace key closes only the last handle that was created locally.

    The demo has been compiled under PB/CC 5.01. I would assume that it works with PB/Win,
    if the #CONSOLE OFF is left out.

    Gert Voland.


    Code:
    ' SetMutex.bas
    
    ' Compiler:     PBCC 5.01
    ' OS:           Windows XP
    ' Author:       Gert Voland
    ' Date:         20. Apr. 2009
    
    #COMPILE EXE "SetMutex_Test.exe"
    #DIM ALL
    #CONSOLE OFF
    
    #INCLUDE "Win32Api.inc"
    
    $ProgName = "SetMutex_Test.exe"
    
    '---------------------------------------------------------------
    
    FUNCTION PBMAIN () AS LONG
    
        LOCAL x$, y$, lasty$, txt$
        LOCAL ret, last     AS LONG
        LOCAL hGW, hDC      AS DWORD
        LOCAL hFont         AS LONG
        LOCAL i, ist        AS LONG
        LOCAL pID           AS DWORD
    
        ' Use it here for flagging this test program
        IF SetMutex($ProgName, 0) = 0 THEN                  ' Check
            ' It does not exist yet -> create it
            SetMutex($ProgName, 1)                          ' Create
            txt$ = "First instance of " + $ProgName
            pID = SHELL($ProgName, 1)                       ' Start two more instances of this program
        ELSE
            ' It is already loaded
            txt$ = "Another instance of " + $ProgName       ' Note: This does not get updated when the first instance terminates
        END IF
    
        IF pID > 0 THEN
            GRAPHIC WINDOW txt$, 10,  10,  280, 500 TO hGW
        ELSE
            GRAPHIC WINDOW txt$, 310,  10,  280, 500 TO hGW
        END IF
        GRAPHIC ATTACH hGW, 0, REDRAW
    
        FONT NEW "Courier New", 9 TO hFont
        GRAPHIC SET FONT hFont
    
        ' Use it here to create, check and destroy more Mutexes
        DO
            GRAPHIC GET DC TO hDC
            IF hDC = 0 THEN EXIT LOOP                               ' In case GW has been closed externally
    
            SLEEP 0                                                 ' Allow some CPU to other processes
            GRAPHIC CLEAR                                           ' Always start at top
            GRAPHIC PRINT " Press the following keys for testing:
            GRAPHIC PRINT
            GRAPHIC PRINT " Create: A - Z  Destroy: BS  Quit: Esc"
    
            GRAPHIC INSTAT TO ist
            IF ISTRUE ist THEN
                GRAPHIC INKEY$ TO x$
                x$ = UCASE$(x$)
            ELSE
                x$ = ""
            END IF
    
            SELECT CASE x$
                CASE "A" TO "Z"
                    y$ = "Mutex_" + x$
                    ret = SetMutex(y$, 1)                               ' Create Mutex
                    IF ret > 0 THEN
                        last = ret                                      ' Mutex did not exist yet - it is the last one being created
                        lasty$ = y$                                     ' Remember the last one
                    END IF
    
                CASE $BS                                                ' Only close the handle created last!
                    IF last > 0 THEN
                        CloseHandle(last)
                        last = 0                                        ' Forget the last one
                        lasty$ = ""
                    END IF
    
                CASE $ESC
                    EXIT LOOP
    
            END SELECT
    
            GRAPHIC PRINT
    
            FOR i = ASC("A") TO ASC("Z")
                y$ = "Mutex_" + CHR$(i)
                ret = SetMutex(y$)                                  ' Check Mutex
    
                GRAPHIC PRINT " "; y$; "   ";
                SELECT CASE ret
                    CASE 0
                        GRAPHIC PRINT "---"
    
                    CASE -1
                        IF y$ = lasty$ THEN
                            GRAPHIC PRINT "last handle created :"; USING$(" ####", last)
                        ELSE
                            GRAPHIC PRINT "exists"
                        END IF
    
                END SELECT
            NEXT i
    
            GRAPHIC REDRAW
        LOOP
    
        GRAPHIC WINDOW END
    
    END FUNCTION
    
    '---------------------------------------------------------------
    
    FUNCTION SetMutex(BYVAL szMutexName AS ASCIIZ * 64, OPT BYVAL createMx AS LONG) AS LONG
    ' #INCLUDE "Win32API.inc"    ' needed
    '
    ' Purpose:  Test if a command/routine/program has been activated by means of a named Mutex.
    '
    ' Usage:
    ' (1) The first call of  SetMutex("MutexName", 1)  creates a Mutex and returns the create-handle.
    '     It may be kept for possibly using  CloseHandle() later.
    '
    ' (2) When a Mutex is checked (in whichever program) by  SetMutex("MutexName", 0)  an OpenMutex is executed.
    '     The open-handle gets closed again. Thus, the creating program is the only one to keep the Mutex handle.
    '     Almost any type of activity can be monitored this way, e.g. if a program is loaded,
    '     or if part of a program is active (or done), etc.
    '
    ' (3) Optionally one can destroy the Mutex using  CloseHandle(create-handle)  in the program where it was created.
    '     Still, when the creating program terminates, the Mutex object gets destroyed in any case.
    '
    ' (4) Limitation: A non-creating program cannot find out which program created the Mutex.
    '                 For that, more inter-process communication is needed.
    '
    ' Input:    szMutexName         :  Name of the Mutex to be created or checked (here limited to 63 characters)
    '           createMx (optional) :  1 => Create the Mutex,  0 => Check the Mutex
    '
    ' Output:   FUNCTION = 0        :  Mutex does not exist
    '                    = > 0      :  = Handle hMutex after creating Mutex
    '                    = -1       :  Mutex exists
    
        LOCAL hMutex    AS LONG     ' Create-handle of Mutex
    
        IF createMx = 0 THEN
            ' Check existence. Do not create a new handle, though.
            hMutex = OpenMutex(BYVAL %MUTEX_ALL_ACCESS, BYVAL 0, szMutexName)
            IF hMutex = 0 THEN
                ' No need to close a handle; there is none.
                FUNCTION = 0                                        ' Mutex does not exist
            ELSE
                ' Close the open-handle
                CloseHandle(hMutex)
                FUNCTION = -1                                       ' Mutex exists
            END IF
        ELSE
            ' Create a Mutex
            hMutex = CreateMutex(BYVAL 0, BYVAL 1, szMutexName)
            IF GetLastError = %ERROR_ALREADY_EXISTS THEN
                ' Close this handle in order to keep only the first create-handle
                CloseHandle hMutex
                FUNCTION = -1                                       ' Mutex exists
            ELSE
                ' Do not close the create-handle. The calling program is the only one to "keep" the handle
                FUNCTION = hMutex                                   ' Return the Mutex create-handle
            END IF
        END IF
    
    END FUNCTION    ' SetMutex
    
    '---------------------------------------------------------------

    Attached are .bas and .exe.
    Gert Voland
Working...
X