|
-
November 8th, 2010, 04:23 PM
#6
Re: Trying to resolve a locking thread
Thank you all, guys. And I apologize for this delay. Let me address your points.
 Originally Posted by Igor Vartanov
Exhaustive logging operations may help...
As you also pointed out, Igor, they can also interfere with the thread timings. I don't know if I mentioned this but I could not reproduce this behavior on my system. The only indication that this happens comes from event logs from a client. And as you also said remote debugging will be quite a cumbersome and probably futile way to address this issue since it will also introduce its own delay. As for minidumps I always had a hard time analyzing them.
 Originally Posted by Igor Vartanov
Never trusted statements like this. You know why?
I agree. And I came off too pompous in it. I put it there so that people weren't asking me to check the synchronization, which was quite simple and shouldn't have caused any issues by itself. [PS. I'm sure this phrase doesn't help the original statement either ]
 Originally Posted by Arjay
How about posting a snippet of the shared resources and how you are using the mutext to protect it? Btw, why are you using a mutex anyway?
I was originally using a critical section but then I had some doubts that maybe it was locking up with a possible repeated call or something, thus I reworked a synchronization object to use the wait on a mutex and a stop event together. Here's a code snippet for a synchronized object:
Code:
enum CS_SYNCH_OBJECTS{
CAE_MUTEX, //Synchronization mutex
CAE_STOP_EVENT, //Stop event
CAE_COUNT //MUST BE LAST!
};
//All calls are unfurled down to bare APIs for readability
struct SYNCHED_V1_DATA{
SYNCHED_V1_DATA()
{
hCSMutex = ::CreateMutex(NULL, FALSE, NULL);
nCntCSObjs = hCSMutex ? 1 : 0;
hSynchObject[CAE_MUTEX] = hCSMutex;
nV1 = 0;
}
~SYNCHED_V1_DATA()
{
UnloadAll();
}
void UnloadAll()
{
if(hCSMutex)
CloseHandle(hCSMutex);
hCSMutex = NULL;
nCntCSObjs = 0;
}
BOOL Initialize(HANDLE hStopEvent)
{
//Initialize the synchronization objects with a "stop event"
//RETURN: = TRUE if success
if(hStopEvent)
{
hSynchObject[CAE_STOP_EVENT] = hStopEvent;
nCntCSObjs = CAE_STOP_EVENT + 1;
}
return hSynchObject[CAE_STOP_EVENT] && hSynchObject[CAE_MUTEX] && nCntCSObjs == CAE_COUNT;
}
BOOL Get_nV1(int& v1)
{
//"GET" method
//RETURN: TRUE if stop event is set (thus, need to exit ASAP w/o any further processing)
BOOL bR = ::WaitForMultipleObjects(nCntCSObjs, hSynchObject, FALSE, INFINITE) == (WAIT_OBJECT_0 + CAE_STOP_EVENT);
V1 = nV1;
ReleaseMutex(hSynchObject[CAE_MUTEX]);
return bR;
}
BOOL Set_nV1(int V1)
{
//"SET" method
//RETURN: TRUE if stop event is set (thus, need to exit ASAP w/o any further processing)
BOOL bR = ::WaitForMultipleObjects(nCntCSObjs, hSynchObject, FALSE, INFINITE) == (WAIT_OBJECT_0 + CAE_STOP_EVENT);
nV1 = V1;
ReleaseMutex(hSynchObject[CAE_MUTEX]);
return bR;
}
private:
HANDLE hCSMutex; //Synchronization mutex
HANDLE hSynchObject[CAE_COUNT]; //Synchronization objects
int nCntCSObjs; //Number of valid objects in 'hSynchObject'
int nV1; //Object being synch'ed
//Copy constructor and assignments are NOT available!
//(Create new object instances instead)
SYNCHED_V1_DATA(const SYNCHED_V1_DATA& s)
{
}
SYNCHED_V1_DATA& operator = (const SYNCHED_V1_DATA& s)
{
}
};
 Originally Posted by Arjay
As an idea of what can go wrong, consider the following code:
Code:
while( TRUE )
{
switch( WaitForMultipleEvents( .... ) )
case WAIT_OBJECT_0 + 0: // Shutdown event
return 1;
break;
case WAIT_OBJECT_0 + 1:
DoGraphicsWork( );
break;
... more switch cases
}
Yes, that is exactly how it goes inside each worker thread, and I understand that if execution locks somewhere within DoGraphicsWork( ); it will pose a problem. But since it's a graphics rendering thread everything should be running (fairly) quickly within the DoGraphicsWork( ); method, that should definitely return within 5 second margin.
 Originally Posted by Alex F
Does this happen only when stop event is set?
Yes.
 Originally Posted by Alex F
hEventStopNow should be manual reset event
Yes, of course.
 Originally Posted by Alex F
Every wait operation in both threads must include hEventStopNow
Yes, of course.
 Originally Posted by Zaccheus
Could using GDI+ from a worker thread be causing problems?
Thank you for bringing it up because that was my main concern. In the back of my head I thought, "what if GDI+ does not support multi-threading like I do it here?" I still don't know the answer, by the way.
But I think I found a possible culprit for this issue (which is less mundane). I found one SendMessage in the worker thread that is calling to the main thread and that is a red flag #1. So I replaced it with a PostMessage and now have to wait if the glitch repeats again. (Which is quite painful by itself.)
On a side note, I want to ask you. This was always confusing for me, since some system APIs can call SendMessage themselves internally. One of my worker threads may call GetWindowLongPtr(GWL_STYLE), SetWindowLongPtr(GWL_STYLE) and SetWindowPos(). Can those APIs call SendMessage internally?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|