21.03.2013 Views

Problem - Kevin Tafuro

Problem - Kevin Tafuro

Problem - Kevin Tafuro

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

on Unix, you must use a lock file and make sure to avoid a number of possible race<br />

conditions to make lock files work properly. On Windows, however, the use of<br />

named mutexes solves all the problems Unix has without introducing new ones.<br />

A named mutex is a synchronization object that works by allowing only a single<br />

thread to acquire a lock at any given time. Mutexes can also exist without a name, in<br />

which case they are considered anonymous. Access to an anonymous mutex can only<br />

be obtained by somehow acquiring a handle to the object from the thread that created<br />

it. Anonymous mutexes are of no use to us in this recipe, so we won’t discuss<br />

them further.<br />

Mutexes have a namespace much like that of a filesystem. The mutex namespace is<br />

separate from namespaces used by all other objects. If two or more applications<br />

agree on a name for a mutex, access to the mutex can always be obtained to use it for<br />

synchronizing access to a shared resource.<br />

A mutex is created with a call to the CreateMutex( ) function. You will find it particularly<br />

useful in this recipe that the mutex is created and a handle returned, or, if the<br />

mutex already exists, a handle to the existing mutex is returned.<br />

Once we have a handle to the mutex that will be used for synchronization, using it is<br />

a simple matter of waiting for the mutex to enter the signaled state. When it does, we<br />

obtain the lock, and other processes wait for us to release it. When we are finished<br />

using the resource, we simply release the lock, which places the mutex into the signaled<br />

state.<br />

If our program terminates abnormally while it holds the lock on the resource, the<br />

lock is released, and the return from WaitForSingleObject( ) in the next process to<br />

obtain the lock is WAIT_ABANDONED. We do not check for this condition in our code<br />

because the code is intended to be used in such a way that abandoning the lock will<br />

not have any adverse effects. This is essentially the same type of behavior as that in<br />

the Unix lock file code from Recipe 2.9, where it attempts to break the lock if the<br />

process holding it terminates unexpectedly.<br />

To obtain a lock, call SpcLockResource( ) with the name of the lock. If the lock is successfully<br />

obtained, the return will be a handle to the lock; otherwise, the return will<br />

be NULL, and GetLastError( ) can be used to determine what went wrong. When<br />

you’re done with the lock, release it by calling SpcUnlockResource( ) with the handle<br />

returned by SpcLockResource( ).<br />

#include <br />

HANDLE SpcLockResource(LPCTSTR lpName) {<br />

HANDLE hResourceLock;<br />

if (!lpName) {<br />

SetLastError(ERROR_INVALID_PARAMETER);<br />

return 0;<br />

}<br />

64 | Chapter 2: Access Control<br />

This is the Title of the Book, eMatter Edition<br />

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!