🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #1789

Re: bizarre behaviour of a mutex handler class and std::auto_ptr

#1789
From: Remy Lebeau (TeamB)
Date: Tue, 19 Jun 2007 17:42
179 lines
5792 bytes
"static array?" <nospam@nospam.com> wrote in message
news:4677f486@newsgroups.borland.com...

> I created a class to manage this for me, all I have to do is
> create an instance to aquire the mutex and detroy it to release it.

You are not doing that correctly.

>   if (++GlobalMutexReferenceCount > 1)
>     return;

Only when your class has 1 active instance is the mutex actually
created and obtained.  Any additional instances beyond that in the
same process do not access the mutex at all.

>   FMutexName = "Global\\" + AnsiReplaceText(ALicenseProjectName,
"\\", "_");

The "Global" prefix only works on XP and higher, or Win2000 with
Terminal Services.  Any OS that is older than that will fail to create
the mutex  as "\\" is an illegal character in those versions.  So you
should be checking the OS version in order to decide whether to apply
that prefix or not.

> Looks good - OK - so now an example. In the scope of a function
> that accesses the protected resource I have:

You don't need the auto_ptr at all.  Your class is not derived from
TObject, so there is nothing preventing you from creating the class
directly on the stack.

Try this instead:

    int GlobalMutexReferenceCount = 0;

    __fastcall TLicenseMutexHandler::TLicenseMutexHandler(const
AnsiString &LicenseProjectName)
    {
        if( GlobalMutexReferenceCount == 0 )
            FMutexHandle = CreateMutex(NULL, FALSE,
GetMutexName(LicenseProjectName).c_str());

        ++GlobalMutexReferenceCount;

        if( FMutexHandle )
            WaitForSingleObject(FMutexHandle, INFINITE);
    }

    __fastcall TLicenseMutexHandler::~TLicenseMutexHandler()
    {
        --GlobalMutexReferenceCount;
        if( FMutexHandle )
        {
            ReleaseMutex(FMutexHandle);
            if( GlobalMutexReferenceCount == 0 )
                CloseHandle(FMutexHandle);
        }
    }

    AnsiString __fastcall TLicenseMutexHandler::GetMutexName(const
AnsiString &ALicenseProjectName)
    {
        AnsiString Prefix;
        if( (Win32MajorVersion > 5) || ((Win32MajorVersion == 5) &&
(Win32MinorVersion >= 1)) )
            Prefix = "Global\\";
        return Prefix + AnsiReplaceText(ALicenseProjectName, "\\",
"_");
    }

    void __fastcall Func()
    {
        TLicenseMutexHandler LMH(MainLFName);
        // do stuff to resource
    }


With that said, it is not very efficient to pass the mutex name around
on every instance, especially since most of them will never use it.
If you really want to go this class approach, then you should wrap the
actual mutex in one class that you create only once, and then use
another class to lock/unlock it when needed.  For example (untested):

    class TLicenseMutex
    {
        friend class TLicenseMutex::Lock;

    private:
        HANDLE hMutex;

    public:
        TLicenseMutex(const AnsiString &ProjectName);
        ~TLicenseMutex();

        class Lock
        {
        private:
            TLicenseMutex &refMutex;
            bool bLocked;

        public:
            Lock(TLicenseMutex &Mutex, DWORD Interval = INFINITE);
            ~Lock();

            operator bool () const;
            bool operator ! () const;
        };
    };


    TLicenseMutex::TLicenseMutex(const AnsiString &LicenseProjectName)
        : hMutex(NULL)
    {
        AnsiString Prefix;

        if( (Win32MajorVersion > 5) || ((Win32MajorVersion == 5) &&
(Win32MinorVersion >= 1)) )
            Prefix = "Global\\";

        hMutex = CreateMutex(NULL, FALSE, (Prefix +
AnsiReplaceText(ALicenseProjectName, "\\", "_")).c_str());
    }

    TLicenseMutex::~TLicenseMutex()
    {
        if( hMutex )
            CloseHandle(hMutex);
    }


    TLicenseMutex::Lock::Lock(TLicenseMutex &Mutex, DWORD Interval)
        : refMutex(Mutex), bLocked(false)
    {
        bLocked = (WaitForSingleObject(refMutex.hMutex, Interval) ==
WAIT_OBJECT_0);
    }

    TLicenseMutex::Lock::~Lock()
    {
        if( bLocked )
            ReleaseMutex(refMutex.hMutex);
    }

    TLicenseMutex::Lock::operator bool () const
    {
        return bLocked;
    }

    bool TLicenseMutex::Lock::operator ! () const
    {
        return !bLocked;
    }


Then you can do the following:

    // globally created, or a member of the MainForm, or whatever...
    TLicenseMutex MainMutex(MainLFName);

    void __fastcall Func()
    {
        TLicenseMutex::Lock lock(MainMutex);
        if( lock )
        {
            // do stuff to resource
        }
    }

    void __fastcall Func2()
    {
        TLicenseMutex::Lock lock(MainMutex);
        if( !lock )
            return;
        // do stuff to resource
    }


Gambit
Technical Details
Message-ID: <467815b1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news1.google.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!newspeer1.nwr.nac.net!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail
References: <4677f486@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,1abf1872e1bc6ca3
X-Google-Attributes: gid10cc67,public,usenet
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.nativeapi
References: <4677f486@newsgroups.borland.com>
Subject: Re: bizarre behaviour of a mutex handler class and std::auto_ptr
Date: Tue, 19 Jun 2007 10:42:09 -0700
Lines: 181
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1409
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409
NNTP-Posting-Host: 75.82.252.126
Message-ID: <467815b1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1182274993 75.82.252.126 (19 Jun 2007 10:43:13 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news1.google.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!newspeer1.nwr.nac.net!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail
X-Original-Bytes: 5629