Article View: borland.public.cppbuilder.nativeapi
Article #1789Re: bizarre behaviour of a mutex handler class and std::auto_ptr
From: Remy Lebeau (TeamB)
Date: Tue, 19 Jun 2007 17:42
Date: Tue, 19 Jun 2007 17:42
179 lines
5792 bytes
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-mailReferences:
<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