Sign in to follow this  
Lord Darkblade

Mutex under Win32 (and std::vector)

Recommended Posts

Lord Darkblade    122
Mental block time: I have 2 classes and a struct: Mutex_Group - manages a group of mutexes allowing them to be easily refered to. Mutex - a mutex object that know about acquire / release and its own name mutex_X - a struct containing a Mutex and a direction (currently unused) When I create a mutex using Mutex.create(<name>) it creates a new mutex successfully (CreateMutex(...) as per win32), this mutex can then be successfully locked, unlocked etc. However if I create a temp object:
mutex_X temp;
temp.direction = 0;
temp.mutex.create(<name>);
list_of_mutexes.push_back(temp);
When I subsequently iterate through the vector the pushed back temp can be found by name, however the handle of the mutex, despite pointing to the same location in memory is now invalid, even though I had not attempted to kill it. Any thoughts? Do vectors do strange things with pointers?

Share this post


Link to post
Share on other sites
Agony    3452
You probably want the temp mutex object to close the handle when it destructs. This is appropriate behavior. What you're probably missing is when the temp mutex object is copied. You need to add a reference for the new object, so that when the temp object closes the handle, the new object still refers to the mutex and it doesn't get closed. In this case, I believe DuplicateHandle() is what you need, and you need this for both the copy constructor and the assignment operator.


class Mutex
{
public:
//Main Constructor
Mutex(const std::string& Name);

//Copy Constructor
Mutex(const Mutex& mutex);

//Assignment Operator
Mutex& operator = (const Mutex& mutex);

//Destructor
~Mutex();

private:
void Destroy();

HANDLE mhMutex;
};

Mutex::Mutex(const std::string& Name) : mhMutex(NULL)
{
mhMutex = CreateMutex(NULL, FALSE, Name.c_str());
}

Mutex::Mutex(const Mutex& mutex) : mhMutex(NULL)
{
*this = mutex;
}

Mutex& Mutex::operator = (const Mutex& mutex)
{
if (this != &mutex)
{
Destroy();

DuplicateHandle(GetCurrentProcess(), mutex.mhMutex, GetCurrentProcess(), &mhMutex, 0, FALSE, DUPLICATE_SAME_ACCESS);
}
}

Mutex::~Mutex()
{
Destroy();
}

void Mutex::Destroy()
{
if (mhMutex != NULL)
{
CloseHandle(mhMutex);
mhMutex = NULL;
}
}

Share this post


Link to post
Share on other sites
Lord Darkblade    122
When I implement the Duplicatehandle line as you have it I get a C2662 error: Cannot convert from const class x to class x.

const_cast<x> () does not seem to want to remove this constness either, any hints?

Share this post


Link to post
Share on other sites
Agony    3452
I forgot the "return *this;" in operator =, you added that in correctly.

As for the const conversion, I don't know what to say. I just tested it in VC6 and VC8, and both compiled fine. What compiler do you have? Also, what is HANDLE #define-d or typedef-ed as? On my machine with both VC6 and VC8 it is typedef-ed as a void*; apparently the compilers don't mind ignoring const-correctness on void pointers?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this