Sign in to follow this  
AndyEsser

Mutex Object Problems

Recommended Posts

Hi All,

For some time now I've had my engine doing multithreading, specifcally 1 Render Thread, and 1 Thread for everything else (Game Logic, Message Handling, etc). The Game Logic, Asset Loading, and AI will eventually be split out from the Main thread, but for the moment that's how it is.

Until recently, I've been 'winging it' with regards to using Mutexes. I've kinda of just hoped for the best, so haven't bothered to included Mutexes. Well I've finally gotten hacked off with the Access Violations I get and other problems when the Rendering Thread is trying to access something at the same time as the other thread. So today I implemented Mutexes into my Texture class.

I basically have two private member functions in the Texture Class, as shown below.

[code]
bool Texture::GetAccess()
{
DWORD dwResult;

dwResult = WaitForSingleObject(hMutex, 5);

switch (dwResult)
{
case WAIT_OBJECT_0:
return true;
break;

default:
return false;
}
}

bool Texture::ReleaseAccess()
{
bool status = false;

status = GetAccess();
ReleaseMutex(hMutex);

return status;
}
[/code]

hMutex is a HANDLE declared as private in the Texture class declaration.

In the constructor of Texture I have called:

[code]
hMutex = CreateMutex(NULL, FALSE, NULL);
[/code]

Any functions in the class that require access to any potentially dangerous data in the class is surrounded by:

[code]
if (GetAccess())
{
/// Appropriate Code goes in here

ReleaseAccess();
}
[/code]

Logically, this would mean at any time a call that needs to access dangerous data first checks that the Mutex is available, if it isn't it just skips over and continues. If it is then it proceeds. And once it's finished it releases the Mutex.

Now that's the background out of the way.

The problem I'm having is, if I load a Texture in the Renderer thread it works fine. However, if I try to load a texture from the Logic Thread, then I get an Access Violation on the call to WaitForSingleObject(hMutex, 5); in the GetAccess() function.

I'm using Visual Studio 2010, on Windows 7 64-bit.

Any thoughts?

Share this post


Link to post
Share on other sites
For starters, you may want to look at [url="http://msdn.microsoft.com/en-us/library/ms682530%28v=vs.85%29.aspx"]Critical Section Objects[/url], as they are a bit less heavyweight if you are doing a lot of locking.
Secondly, to quote MSDN on [url="http://msdn.microsoft.com/en-us/library/ms684266%28v=vs.85%29.aspx"]Mutex[/url]: "the thread must call [url="http://msdn.microsoft.com/en-us/library/ms685066%28v=vs.85%29.aspx"][b]ReleaseMutex[/b][/url] once for each time that the mutex satisfied the conditions of a wait function.". Thus, the call chain of "GetAccess(); ReleaseAccess();" waits twice, but releases once. That may be an issue.
As far as your access violation, the other obvious place to look is your texture itself. Make sure the texture object in your logic thread was fully constructed at the time you call GetAccess() on it. If you were creating in one thread and using in the other, you should synchronize the creation and first use to make sure it is fully created in thread X before thread Y starts using it.

Share this post


Link to post
Share on other sites
Well the texture class is fully instantiated - and data is loaded into the class before it's passed to the Rendering pipeline, so should be fully loaded before the Rendering Thread tries to access it.

I'll take a look at Critical Section Objects and see if I can make that work.

Many thanks KulSeran.

Share this post


Link to post
Share on other sites
I've just had a thought.

When I pass the Texture class to the rendering pipeline, I pass it's pointer and it gets added to a std::vector as a push_back() operation.

Could something in the copy operation in be causing a problem with the CRITICAL_SECTION/MUTEX variable?

Share this post


Link to post
Share on other sites
You should not call GetAccess from ReleaseAccess.

The calling thread already has access.

The access violation suggests the handle is invalid. Could the handle be out of sync, overwritten or accidently released?
Could the texture object be falling out of scope after its pointer is passed? Or otherwise be deleted?
I would check the value of the handle after creation and again on the exception.

Share this post


Link to post
Share on other sites
[quote name='AndyEsser' timestamp='1302809584' post='4798522']When I pass the Texture class to the rendering pipeline, I pass it's pointer and it gets added to a std::vector as a push_back() operation.[/quote]Do you ensure mutually exclusive access to the vector via a critical section?
You can't have one thread pushing to a vector while another one is reading from the vector - that will certainly causes corruption/crashes.

Share this post


Link to post
Share on other sites
I managed to solve the Access Violation by moving the InitializeCriticalSection() into a separate function, rather than in the Constructor. It would be something funky was happening when I dropped the Textures pointer onto the Vector. Will need to investigate that further, but at least it's not crashing.

@Hodgman: I had thought about this, and I'll implement it this evening.

Right now, other problems have reared up.

Thanks for all your help.

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