Threading newbie with issue with runaway threads
Ok, to you understand I will explain the problem: I am using a library called ClanLIB (not my choice), that library, SEEMLY (I am not certain, even reading the sourcE), creates a thread that handles sound.
This thread, when the buffer is empty, tries to fetch more data, usually this cause a underrun when the data generating library is too slow to give more data before the soundcard reaches the buffer end.
So I added my own thread, that keeps generating sound on the background.
This worked fine, except that my own thread sometimes hijacked too much CPU time and froze everything else. To fix it, I added a conditional wait.
The conditional wait happens when the buffer is full, and when ClanLIB ask for more data, the wait is signaled, thus the buffer write thread resumes (until it is full again).
My issue is that since I added this conditional wait, the ClanLIB sound thread, and my own music thread, SOMETIMES get "runaway", playing music while the rest of the application freezes.
What sort of strange c开发者_开发百科ondition would cause that?
pseudocode:
//main thread (that get frozen)
start_sound_thread();
do_lots_of_stuff();
quit();
//Sound Thread:
While(true)
{
play(buffer);
if(buffer_empty)
{
mutex.lock()
buffer = buffer2;
if(buffer2_full)
{
signal(cond1);
buffer2_full = false;
}
mutex.unlock()
}
}
//Music Library Thread:
while(true)
{
mutex.lock()
if( check_free_space(buffer2) == 0)
{
buffer2_full = true;
condition_wait(cond1);
}
write_music(buffer2);
mutex.unlock()
}
You're doing WAY too much within the mutex zones - it's likely you are deadlocking on the cond1 signal. You should do as little as possible within locking regions, because the more you do, the more risk you will introduce a deadlock - and you absolutely should never wait on a signal inside of a mutex that guards the sending of the signal - if you're waiting, it isn't ever going to be sent - condition_wait is not unblocking your mutex object, how could it know about it ?
The 'solved by addition of conditional waits' is a strong indicator you've got a race condition leading to deadlock - you haven't solved the problem, as soon as the execution timing of your logic changes for any reason, say because another app is running, the deadlock can return.
I'm using clanlib for a project too, but using OpenAL for sound. It seems to work the same way with feeding the buffer etc.
I also use a seperate thread for sound, but my solution was to just add a fixed sleep period after each attempt to feed the buffer. It's simple and seems pretty solid. And no locking is required ;)
I actually, don't know what the issue was, it was fixed by accident...
I had a related issue, this one was caused by race condition when deleting the thread... I moved some code around (I don't even needed to recode anything) and it went away too. Now the thing is perfectly stable! (well, still has underruns but they are more rare now)
If you are using ClanLib game SDK it is a well establish, tested and supported SDK. No offence intended, but, as you are an admitted newbie, the problem is more likely in your code than theirs.
I find it difficult to believe that such a well established library would develop an underrun, and, even if it it does, I doubt that the best solution would be to added my own thread, that keeps generating sound on the background
. I say this because I suspect that you are taking the wrong approach and that if you can find a solution with ClanLib then you won't need your thread & your problem will be gone without needing to be solved.
It is goo that you posted code, thanks. I'll go off and look at that now.
And, finally, as great a fan as I am of SO, wouldn't it be better to ask first at the official ClanLib forum first?
Edit: what makes you so sure it is an underrun? i still find that hard to believe, but if you cna detect it in your program, then why not sleep()
, rather than generating sound? (how long to sleep? how do you know how much sound to generate? and doesn't that generated sound interfere with the "real" sound?)
精彩评论