<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>[A5] simple multithread code acts weird</title>
		<link>http://www.allegro.cc/forums/view/607730</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Fri, 01 Jul 2011 22:07:37 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>hi <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" /><br />so, i&#39;m doing this:</p><div class="source-code snippet"><div class="inner"><pre><span class="c">//thread 1:</span>
<a href="http://www.allegro.cc/manual/al_lock_mutex"><span class="a">al_lock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_start_thread"><span class="a">al_start_thread</span></a><span class="k2">(</span>thread2<span class="k2">)</span><span class="k2">;</span> 
<span class="k1">for</span><span class="k2">(</span><span class="c">/*some condition*/</span><span class="k2">)</span><span class="k2">{</span>
  <a href="http://www.allegro.cc/manual/al_wait_cond"><span class="a">al_wait_cond</span></a><span class="k2">(</span>sig,job<span class="k2">)</span><span class="k2">;</span> 
<span class="k2">}</span>

<span class="c">//thread 2:</span>
<span class="k1">while</span><span class="k2">(</span><span class="n">1</span><span class="k2">)</span><span class="k2">{</span>
  <a href="http://www.allegro.cc/manual/al_lock_mutex"><span class="a">al_lock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span> 
  <span class="c">/* work... */</span>
  <a href="http://www.allegro.cc/manual/al_signal_cond"><span class="a">al_signal_cond</span></a><span class="k2">(</span>sig<span class="k2">)</span><span class="k2">;</span>
  <a href="http://www.allegro.cc/manual/al_unlock_mutex"><span class="a">al_unlock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span>
<span class="k2">}</span>
</pre></div></div><p>

i&#39;ve read the pthreads docs and googled for quite a few hours now. as far as i understand:<br />-thread1 gets the mutex, thread2 starts and waits.<br />-when i call wait_cond, thread1 starts waiting and unlocks the mutex, so thread2 can do some work. this apparently is atomic.<br />-now, thread2 signals and unlocks. when these 2 conditions are met, the wait in thread1 wakes up and gets back the mutex. this last step done by wait_cond should be atomic as well, but apparently is not.</p><p>what happens is that thread2 gets the mutex &quot;while&quot; thread1 is waking up.</p><p>if i add a small al_rest delay after the wait_cond, i get this behavior 100% of the time. if i add this delay after thread2 unlocks, thread1 gets the mutex first and works like i want it to :p</p><p>where am i being stupid? <img src="http://www.allegro.cc/forums/smileys/cheesy.gif" alt=":D" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (rocket1)</author>
		<pubDate>Fri, 01 Jul 2011 16:48:09 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/607730/923265#target">rocket1</a> said:</div><div class="quote"><p>what happens is that thread2 gets the mutex &quot;while&quot; thread1 is waking up.</p></div></div><p>

What do you mean? Can you extend the example with some printfs and then say what you expect it to print but what it prints instead?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Elias)</author>
		<pubDate>Fri, 01 Jul 2011 18:09:24 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The problem is that thread2 sometimes acquires the mutex before thread1 acquires the mutex. You can picture thread2 like this:</p><div class="source-code snippet"><div class="inner"><pre><span class="c">//thread2</span>
<a href="http://www.allegro.cc/manual/al_lock_mutex"><span class="a">al_lock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span> 
<span class="c">/* work... */</span>
<a href="http://www.allegro.cc/manual/al_signal_cond"><span class="a">al_signal_cond</span></a><span class="k2">(</span>sig<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_unlock_mutex"><span class="a">al_unlock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_lock_mutex"><span class="a">al_lock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span> 
<span class="c">/* work... */</span>
<a href="http://www.allegro.cc/manual/al_signal_cond"><span class="a">al_signal_cond</span></a><span class="k2">(</span>sig<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_unlock_mutex"><span class="a">al_unlock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span>
...
</pre></div></div><p>

As you can see, thread2 unlocks the mutex and then immediately locks it. If you put<br />al_rest after al_unlock_mutex, like this:</p><div class="source-code snippet"><div class="inner"><pre><span class="c">//thread2</span>
<a href="http://www.allegro.cc/manual/al_lock_mutex"><span class="a">al_lock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span> 
<span class="c">/* work... */</span>
<a href="http://www.allegro.cc/manual/al_signal_cond"><span class="a">al_signal_cond</span></a><span class="k2">(</span>sig<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_unlock_mutex"><span class="a">al_unlock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_rest"><span class="a">al_rest</span></a><span class="k2">(</span><span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_lock_mutex"><span class="a">al_lock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span> 
<span class="c">/* work... */</span>
<a href="http://www.allegro.cc/manual/al_signal_cond"><span class="a">al_signal_cond</span></a><span class="k2">(</span>sig<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_unlock_mutex"><span class="a">al_unlock_mutex</span></a><span class="k2">(</span>job<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_rest"><span class="a">al_rest</span></a><span class="k2">(</span><span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
...
</pre></div></div><p>

then your code works because thread1 is given a chance to do its work.</p><p>In order to achieve what you want, you need a semaphore: the worker thread increments the semaphore, and the waiting thread decrements the semaphore or waits for the semaphore to be incremented.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Fri, 01 Jul 2011 18:51:21 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>thanks for the reply</p><p>let me do the steps from the start:</p><p>t1 locks<br />t2 waits on lock<br />t1 waits on cond and unlocks</p><p>t2 now can lock<br />t2 does some work <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" /><br />t2 signals<br />t2 unlocks</p><p><b>t1 does not react</b><br />t2 locks again (it&#39;s the first line in the while loop)<br />t2 signals again<br />t2 unlocks again</p><p>t2 locks again (same thing..)</p><p>now t2 apparently takes control forever and t1 still has to do anything. it&#39;s in wait_cond limbo <img src="http://www.allegro.cc/forums/smileys/cheesy.gif" alt=":D" /><br />if i add a delay in t2, after t2 unlocks, it looks like i&#39;m giving the time to wait_cond in t1 to get the mutex and exit the limbo <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" /></p><p>for obvious reasons, adding a delay should not be necessary..
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (rocket1)</author>
		<pubDate>Fri, 01 Jul 2011 18:52:10 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>There is no guarantee that the thread that is woken up by al_signal_cond will run immediately. What happens under the hood is that the operating system puts the thread in a queue for execution. In the mean time, the other thread gets another execution slot from the operating system, and locks the mutex.</p><p>You need a semaphore.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Fri, 01 Jul 2011 18:57:35 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/607730/923274#target">rocket1</a> said:</div><div class="quote"><p>t1 does not react</p></div></div><p>
It isn&#39;t supposed to.<br />Signaling an event/cond does not mean that the waiting thread immediately gets to run, it only means the OS will now again be able to schedule it to run.<br />Also, when t2 signals/unlocks it does not give up its time to run - it continues running until the OS tells it to stop; However if you add al_rest(0) then t2 is telling to OS to take back its remaining run-time and schedule it to run again later. This is why adding a rest in t2 seems to help you, as t1 can be scheduled after t2.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Slartibartfast)</author>
		<pubDate>Fri, 01 Jul 2011 18:58:30 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>thanks for the replies <img src="http://www.allegro.cc/forums/smileys/cheesy.gif" alt=":D" /><br />exactly as some of you suggested, i was expecting the wait_cond to get back the mutex atomically.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (rocket1)</author>
		<pubDate>Fri, 01 Jul 2011 19:07:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>wait_cond will atomically lock the mutex before continuing. The issue is that thread 1 never gets to run because whenever its woken up most likely the mutex is locked by t2.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (kazzmir)</author>
		<pubDate>Fri, 01 Jul 2011 22:07:37 +0000</pubDate>
	</item>
</rss>
