<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Callback Problem</title>
		<link>http://www.allegro.cc/forums/view/589912</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Sun, 18 Feb 2007 19:27:59 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Im new to callbacks, I am trying to make an input buffer with a callback<br />so that i wont miss out inputs while doing lazy processing..</p><p>this is what i came up with
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">typedef</span> <span class="k1">struct</span> _message</td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>  <span class="k1">char</span> type<span class="k2">;</span></td></tr><tr><td class="number">4</td><td>  <span class="k1">int</span> val<span class="k2">;</span></td></tr><tr><td class="number">5</td><td>  <span class="k1">int</span> ex1, ex2, ex3<span class="k2">;</span></td></tr><tr><td class="number">6</td><td><span class="k2">}</span> message<span class="k2">;</span></td></tr><tr><td class="number">7</td><td><span class="k1">typedef</span> <span class="k1">struct</span> _input</td></tr><tr><td class="number">8</td><td><span class="k2">{</span></td></tr><tr><td class="number">9</td><td>   message queue<span class="k2">[</span><span class="n">255</span><span class="k2">]</span><span class="k2">;</span></td></tr><tr><td class="number">10</td><td>   <span class="k1">unsigned</span> <span class="k1">int</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_539.html" target="_blank">lock</a>, start, end<span class="k2">;</span></td></tr><tr><td class="number">11</td><td><span class="k2">}</span> input<span class="k2">;</span></td></tr><tr><td class="number">12</td><td>&#160;</td></tr><tr><td class="number">13</td><td><span class="k1">volatile</span> input buf<span class="k2">;</span></td></tr><tr><td class="number">14</td><td>&#160;</td></tr><tr><td class="number">15</td><td><span class="k1">void</span> mouse_call<span class="k2">(</span><span class="k1">int</span> f<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">16</td><td>   <span class="k1">unsigned</span> <span class="k1">int</span> i, ex1 <span class="k3">=</span> <span class="n">0</span>, ex2 <span class="k3">=</span> <span class="n">0</span>, ex3 <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">17</td><td>  </td></tr><tr><td class="number">18</td><td>   <span class="k1">if</span><span class="k2">(</span>f <span class="k3">&amp;</span> MOUSE_FLAG_MOVE<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">19</td><td>      ex1 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_x" target="_blank"><span class="a">mouse_x</span></a><span class="k2">;</span></td></tr><tr><td class="number">20</td><td>      ex2<span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_y" target="_blank"><span class="a">mouse_y</span></a><span class="k2">;</span></td></tr><tr><td class="number">21</td><td>   <span class="k2">}</span></td></tr><tr><td class="number">22</td><td>   <span class="k1">if</span><span class="k2">(</span>f <span class="k3">&amp;</span> MOUSE_FLAG_MOVE_Z<span class="k2">)</span></td></tr><tr><td class="number">23</td><td>      ex3 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_z" target="_blank"><span class="a">mouse_z</span></a><span class="k2">;</span></td></tr><tr><td class="number">24</td><td>   </td></tr><tr><td class="number">25</td><td>   <span class="k1">if</span><span class="k2">(</span><span class="k2">(</span><span class="k2">(</span>buf.end<span class="k3">+</span><span class="n">1</span><span class="k2">)</span> <span class="k3">&amp;</span> <span class="n">255</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k2">(</span>buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span><span class="k2">)</span> <span class="c">//What! buffer is full?</span></td></tr><tr><td class="number">26</td><td>      <span class="k1">return</span><span class="k2">;</span></td></tr><tr><td class="number">27</td><td>   i <span class="k3">=</span> buf.end<span class="k3">&amp;</span><span class="n">255</span><span class="k2">;</span></td></tr><tr><td class="number">28</td><td>   buf.lock<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span> <span class="c">//Lock</span></td></tr><tr><td class="number">29</td><td>   <span class="k1">if</span><span class="k2">(</span>buf.lock <span class="k3">!</span><span class="k3">=</span> <span class="n">1</span><span class="k2">)</span> <span class="k2">{</span> <span class="c">//Damn! its locked</span></td></tr><tr><td class="number">30</td><td>      buf.lock--<span class="k2">;</span></td></tr><tr><td class="number">31</td><td>      <span class="k1">return</span><span class="k2">;</span></td></tr><tr><td class="number">32</td><td>   <span class="k2">}</span></td></tr><tr><td class="number">33</td><td>   </td></tr><tr><td class="number">34</td><td>   buf.end<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span> <span class="c">//Quickly copy stuff</span></td></tr><tr><td class="number">35</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.type <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">36</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.val <span class="k3">=</span> f<span class="k2">;</span></td></tr><tr><td class="number">37</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.ex1 <span class="k3">=</span> ex1<span class="k2">;</span></td></tr><tr><td class="number">38</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.ex2 <span class="k3">=</span> ex2<span class="k2">;</span></td></tr><tr><td class="number">39</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.ex3 <span class="k3">=</span> ex3<span class="k2">;</span></td></tr><tr><td class="number">40</td><td>&#160;</td></tr><tr><td class="number">41</td><td>   buf.lock--<span class="k2">;</span></td></tr><tr><td class="number">42</td><td><span class="k2">}</span></td></tr><tr><td class="number">43</td><td><a href="http://www.allegro.cc/manual/END_OF_FUNCTION" target="_blank"><span class="a">END_OF_FUNCTION</span></a><span class="k2">(</span>mouse_call<span class="k2">)</span></td></tr></tbody></table></div></div><p>

Then in main:
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td>   <a href="http://www.allegro.cc/manual/LOCK_VARIABLE" target="_blank"><span class="a">LOCK_VARIABLE</span></a><span class="k2">(</span>buf<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">2</td><td>   <a href="http://www.allegro.cc/manual/LOCK_FUNCTION" target="_blank"><span class="a">LOCK_FUNCTION</span></a><span class="k2">(</span>mouse_call<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">3</td><td>   <a href="http://www.allegro.cc/manual/LOCK_FUNCTION" target="_blank"><span class="a">LOCK_FUNCTION</span></a><span class="k2">(</span>key_call<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">4</td><td>   <a href="http://www.allegro.cc/manual/mouse_callback" target="_blank"><span class="a">mouse_callback</span></a> <span class="k3">=</span> mouse_call<span class="k2">;</span></td></tr><tr><td class="number">5</td><td>   <a href="http://www.allegro.cc/manual/keyboard_lowlevel_callback" target="_blank"><span class="a">keyboard_lowlevel_callback</span></a> <span class="k3">=</span> key_call<span class="k2">;</span></td></tr><tr><td class="number">6</td><td>   buf.end <span class="k3">=</span> buf.start <span class="k3">=</span> buf.lock <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">7</td><td>   <a href="http://www.allegro.cc/manual/install_mouse" target="_blank"><span class="a">install_mouse</span></a><span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">8</td><td>   <a href="http://www.allegro.cc/manual/install_keyboard" target="_blank"><span class="a">install_keyboard</span></a><span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">9</td><td>   <a href="http://www.allegro.cc/manual/set_keyboard_rate" target="_blank"><span class="a">set_keyboard_rate</span></a><span class="k2">(</span><span class="n">0</span>, <span class="n">0</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">10</td><td>&#160;</td></tr><tr><td class="number">11</td><td>   <span class="k1">unsigned</span> <span class="k1">int</span> k<span class="k2">;</span></td></tr><tr><td class="number">12</td><td>   <span class="k1">while</span><span class="k2">(</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">13</td><td>      <span class="k1">if</span><span class="k2">(</span><span class="k2">(</span>buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k2">(</span>buf.end<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">14</td><td>         <span class="c">//rest(1);</span></td></tr><tr><td class="number">15</td><td>   <span class="k1">continue</span><span class="k2">;</span></td></tr><tr><td class="number">16</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">17</td><td>      k <span class="k3">=</span> buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">;</span></td></tr><tr><td class="number">18</td><td>      <a href="http://www.allegro.cc/manual/textprintf_ex" target="_blank"><span class="a">textprintf_ex</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/screen" target="_blank"><span class="a">screen</span></a>, <a href="http://www.allegro.cc/manual/font" target="_blank"><span class="a">font</span></a>, <span class="n">0</span>, <span class="n">0</span>, <span class="n">3</span>,<span class="n">0</span>, <span class="s">"type = %i val = %i ex1 = %i ex2 = %i ex3 = %i        "</span>, buf.queue<span class="k2">[</span>k<span class="k2">]</span>.type, buf.queue<span class="k2">[</span>k<span class="k2">]</span>.val, buf.queue<span class="k2">[</span>k<span class="k2">]</span>.ex1, buf.queue<span class="k2">[</span>k<span class="k2">]</span>.ex2, buf.queue<span class="k2">[</span>k<span class="k2">]</span>.ex3<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td>      <a href="http://www.allegro.cc/manual/textprintf_ex" target="_blank"><span class="a">textprintf_ex</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/screen" target="_blank"><span class="a">screen</span></a>, <a href="http://www.allegro.cc/manual/font" target="_blank"><span class="a">font</span></a>, <span class="n">0</span>,<span class="n">10</span>, <span class="n">3</span>,<span class="n">0</span>, <span class="s">"start = %i end = %i            "</span>, <span class="k2">(</span>buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span>, <span class="k2">(</span>buf.end<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">20</td><td>      <span class="k1">if</span><span class="k2">(</span>buf.queue<span class="k2">[</span>k<span class="k2">]</span>.val <span class="k3">=</span><span class="k3">=</span> <span class="n">59</span> <span class="k3">&amp;</span><span class="k3">&amp;</span> buf.queue<span class="k2">[</span>k<span class="k2">]</span>.type <span class="k3">=</span><span class="k3">=</span> <span class="n">1</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">21</td><td>        <span class="k1">break</span><span class="k2">;</span></td></tr><tr><td class="number">22</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">23</td><td>      buf.start<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">24</td><td>   <span class="k2">}</span></td></tr></tbody></table></div></div><p>

but after buf.end reaches 255 the program gets stuck.<br />The same program works perfect if i make everything in &#39;input&#39; structure as separate<br />global variables.</p><p>There are No compile Errors</p><p>I compile with -lalleg -O -Wall in Dev-C++<br />Can Someone help
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (dialmformartian)</author>
		<pubDate>Mon, 05 Feb 2007 18:42:20 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Change the 255 to 256 in the declaration of message queue.  When you write over the 256th element, you&#39;re clobbering your control values instead.  </p><p>edit: further commentary:<br />That&#39;s an odd error to make for someone who got the bitwise math right.  <br />I generally haven&#39;t used locking mechanisms like that, not sure if it&#39;s a good idea or not.  Testing suggests that the mouse callback is not re-entrant on windows, but of course that might vary by platform (specifically, it&#39;s probably is re-entrant on DOS, if Allegro still supports DOS).  Even given that it&#39;s re-entrant though, is that really the right way to implement such a thing?  I just have the impression that implementing locking yourself is a bad idea unless you&#39;re an OS or a threading implementation.  <br />I believe it works when not in a struct due to different memory layout - the elements in the struct are generally in order in memory, while stuff outside of structs are generally in reverse order.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Mon, 05 Feb 2007 21:26:56 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Sheesh !! what a silly mistake. I was rather mislead by the complexity<br />of callbacks into thinking that there was no problem with the code.</p><p>thanx a lot.</p><p>I was also a bit skeptic about the implementation. Are there any other <br />better ways to implement such a thing.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (dialmformartian)</author>
		<pubDate>Tue, 06 Feb 2007 10:50:27 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>dialmformartian, how do you make sure your main routine does not read a part of the buffer that has invalid values? the &#39;lock&#39; member does not guarantee you atomic access to the buffer.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Tue, 06 Feb 2007 17:12:08 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I was also a bit skeptic about the implementation. Are there any other<br />better ways to implement such a thing.
</p></div></div><p>

I don&#39;t know.  In my Allegro callbacks, I do not bother locking (A: I think it only matters on DOS, and B: I think it only matters when there is a performance anomaly).  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
dialmformartian, how do you make sure your main routine does not read a part of the buffer that has invalid values? the &#39;lock&#39; member does not guarantee you atomic access to the buffer.
</p></div></div><p>

Hm, yeah, buf.end++ should probably be moved to after the buffer entry becomes valid instead of before, or you have a race condition there.  In the example code the race won&#39;t actually do anything except cause the wrong values to be displayed once in a while, but for a real-world program that could be a serious issue.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Wed, 07 Feb 2007 01:20:48 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Yeah like orz said the buf.end++ should move quite fast enough unless the user is faster than the CPU in giving in inputs (does that work that way??). I just wanted to try this after seeing the CGUI source code. CGUI seemed to implement something of the sort of an input buffer, then reads the buffer and issues messages to widgets. I just didn&#39;t have the patients to figure how it works exactly. (Can any one help)
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (dialmformartian)</author>
		<pubDate>Wed, 07 Feb 2007 17:40:40 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The current system &quot;gives up&quot; (return and discard the event) when mouse_call() and key_call() race each other.</p><p>I&#39;d replace the whole &quot;lock&quot; system by a mutex to cover all operations on <i>start</i> and <i>end</i>. The locking and unlocking are only one function call, and when you use the &quot;official&quot; mutex functions it&#39;s much easier to verify, from reading the code, that the critical section is indeed protected.</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="c">// in key_call and mouse_call:</span></td></tr><tr><td class="number">2</td><td>pthread_mutex_lock<span class="k2">(</span><span class="k3">&amp;</span>event_handler_mutex<span class="k2">)</span><span class="k2">;</span> <span class="c">// &lt;--</span></td></tr><tr><td class="number">3</td><td><span class="k1">if</span><span class="k2">(</span><span class="k2">(</span><span class="k2">(</span>buf.end<span class="k3">+</span><span class="n">1</span><span class="k2">)</span> <span class="k3">&amp;</span> <span class="n">255</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k2">(</span>buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span><span class="k2">)</span> <span class="k2">{</span> <span class="c">//What! buffer is full?</span></td></tr><tr><td class="number">4</td><td>      pthread_mutex_unlock<span class="k2">(</span><span class="k3">&amp;</span>event_handler_mutex<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">5</td><td>      <span class="k1">return</span><span class="k2">;</span></td></tr><tr><td class="number">6</td><td><span class="k2">}</span></td></tr><tr><td class="number">7</td><td>i <span class="k3">=</span> buf.end<span class="k3">&amp;</span><span class="n">255</span><span class="k2">;</span>   </td></tr><tr><td class="number">8</td><td>buf.end<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">9</td><td>pthread_mutex_unlock<span class="k2">(</span><span class="k3">&amp;</span>event_handler_mutex<span class="k2">)</span><span class="k2">;</span> <span class="c">// &lt;--</span></td></tr><tr><td class="number">10</td><td>&#160;</td></tr><tr><td class="number">11</td><td><span class="c">// in main:</span></td></tr><tr><td class="number">12</td><td><span class="k1">while</span><span class="k2">(</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">13</td><td>&#160;</td></tr><tr><td class="number">14</td><td>      pthread_mutex_lock<span class="k2">(</span><span class="k3">&amp;</span>event_handler_mutex<span class="k2">)</span><span class="k2">;</span> <span class="c">// &lt;--      </span></td></tr><tr><td class="number">15</td><td>      <span class="k1">if</span><span class="k2">(</span><span class="k2">(</span>buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="k2">(</span>buf.end<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span><span class="k2">)</span> <span class="k2">{</span> <span class="c">// have one message to process</span></td></tr><tr><td class="number">16</td><td>           <span class="k1">int</span> start_value <span class="k3">=</span> buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">;</span></td></tr><tr><td class="number">17</td><td>           <span class="k1">int</span> end_value <span class="k3">=</span> buf.end<span class="k3">&amp;</span><span class="n">255</span><span class="k2">;</span></td></tr><tr><td class="number">18</td><td>           buf.start<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td>           pthread_mutex_unlock<span class="k2">(</span><span class="k3">&amp;</span>event_handler_mutex<span class="k2">)</span><span class="k2">;</span> <span class="c">// &lt;-- no need to lock DURING the textprintf's</span></td></tr><tr><td class="number">20</td><td>           <a href="http://www.allegro.cc/manual/textprintf_ex" target="_blank"><span class="a">textprintf_ex</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/screen" target="_blank"><span class="a">screen</span></a>, <a href="http://www.allegro.cc/manual/font" target="_blank"><span class="a">font</span></a>, <span class="n">0</span>, <span class="n">0</span>, <span class="n">3</span>,<span class="n">0</span>, <span class="s">"type = %i val = %i ex1 = %i ex2 = %i ex3 = %i        "</span>,</td></tr><tr><td class="number">21</td><td>                buf.queue<span class="k2">[</span>start_value<span class="k2">]</span>.type, buf.queue<span class="k2">[</span>start_value<span class="k2">]</span>.val, buf.queue<span class="k2">[</span>start_value<span class="k2">]</span>.ex1,</td></tr><tr><td class="number">22</td><td>                buf.queue<span class="k2">[</span>start_value<span class="k2">]</span>.ex2, buf.queue<span class="k2">[</span>start_value<span class="k2">]</span>.ex3<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">23</td><td>           <a href="http://www.allegro.cc/manual/textprintf_ex" target="_blank"><span class="a">textprintf_ex</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/screen" target="_blank"><span class="a">screen</span></a>, <a href="http://www.allegro.cc/manual/font" target="_blank"><span class="a">font</span></a>, <span class="n">0</span>,<span class="n">10</span>, <span class="n">3</span>,<span class="n">0</span>, <span class="s">"start = %i end = %i            "</span>,</td></tr><tr><td class="number">24</td><td>                start_value, end_value<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">25</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">26</td><td>      <span class="k1">else</span> <span class="k2">{</span></td></tr><tr><td class="number">27</td><td>           pthread_mutex_unlock<span class="k2">(</span><span class="k3">&amp;</span>event_handler_mutex<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">28</td><td>           <span class="c">//rest(1); // in real situations, you would rest here,</span></td></tr><tr><td class="number">29</td><td>           <span class="c">// or at least do something useful instead of hogging the mutex :)</span></td></tr><tr><td class="number">30</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">31</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Wed, 07 Feb 2007 19:30:02 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Yeah like orz said the buf.end++ should move quite fast enough unless the user is faster than the CPU in giving in inputs (does that work that way??). I just wanted to try this after seeing the CGUI source code. CGUI seemed to implement something of the sort of an input buffer, then reads the buffer and issues messages to widgets. I just didn&#39;t have the patients to figure how it works exactly. (Can any one help)
</p></div></div><p>

I used a critical section. I think it would be better for you to use the library pthreads which is compatible with many platforms.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Wed, 07 Feb 2007 19:30:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
dialmformartian, how do you make sure your main routine does not read a part of the buffer that has invalid values? the &#39;lock&#39; member does not guarantee you atomic access to the buffer.
</p></div></div><p>
</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Hm, yeah, buf.end++ should probably be moved to after the buffer entry becomes valid instead of before, or you have a race condition there. In the example code the race won&#39;t actually do anything except cause the wrong values to be displayed once in a while, but for a real-world program that could be a serious issue.
</p></div></div><p>
</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Yeah like orz said the buf.end++ should move quite fast enough unless the user is faster than the CPU in giving in inputs (does that work that way??).
</p></div></div><p>
Just to make sure we&#39;re on the same page here (because it looks to me like we might, possibly, be talking about different things):<br />What I think axilmar was talking about, and certainly what I was attempting to agree with, is changing this:
</p><div class="source-code snippet"><div class="inner"><pre>   buf.end<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span> <span class="c">//Quickly copy stuff</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.type <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.val <span class="k3">=</span> f<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex1 <span class="k3">=</span> ex1<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex2 <span class="k3">=</span> ex2<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex3 <span class="k3">=</span> ex3<span class="k2">;</span>
</pre></div></div><p>
to this:
</p><div class="source-code snippet"><div class="inner"><pre>   buf.queue<span class="k3">&lt;</span>i&gt;.type <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span><span class="c">//Quickly copy stuff</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.val <span class="k3">=</span> f<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex1 <span class="k3">=</span> ex1<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex2 <span class="k3">=</span> ex2<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex3 <span class="k3">=</span> ex3<span class="k2">;</span>
   buf.end<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span>
</pre></div></div><p>
The idea here being that if buf.end is incremented before buf.queue is updated, then your main loop will notice that buf.end is no longer equal to buf.start, and read out the values of buf.queue, at a time when they may or may not be initialized.  By making that change, the main loop isn&#39;t told about the new mouse event until it&#39;s guaranteed to be able to correctly read buf.queue.  This is known as a race condition; it is a real possibility on windows, though maybe not on DOS.  It would probably be extremely rare, at least on single-core CPUs (the OS scheduler would have to preempt mouse_call after buf.end++ and before buf.lock--). </p><p>Anyway, onward:
</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I just wanted to try this after seeing the CGUI source code. CGUI seemed to implement something of the sort of an input buffer, then reads the buffer and issues messages to widgets.
</p></div></div><p>
I&#39;m not familiar with CGUI, but I am familiar with SDL, which uses an input buffer (patterned after win32 &amp; DirectX I think, though I haven&#39;t done much win32 and/or directX programming).  It is my opinion that input buffers are superior to the polling interface that Allegro offers for large programs, but inferior for small programs.  My current program extends the concept slightly... it timestamps all input, considers time to be an input, and logs all input to file, in order to allow exact program execution to be reproduced, and as a cheap (read: not very good) way to have game mechanics still feel correct when rendering is slow.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I just didn&#39;t have the patients to figure how it works exactly. (Can any one help)
</p></div></div><p>
What&#39;s wrong with your current code?  It appears to buffer mouse events fine.  The keyboard code isn&#39;t posted, but I presume it buffers those okay also.  What are you asking for beyond general commentary on the concept of input buffers in general and/or the specific implementation in CGUI?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Wed, 07 Feb 2007 19:33:46 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Hey thanx Orz for clearing the confusion here.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
It is my opinion that input buffers are superior to the polling interface that Allegro offers for large programs, but inferior for small programs. My current program extends the concept slightly... it timestamps all input, considers time to be an input, and logs all input to file, in order to allow exact program execution to be reproduced, and as a cheap (read: not very good) way to have game mechanics still feel correct when rendering is slow.
</p></div></div><p>

i wanted to create input buffer system because my graph<br />plotter program(which uses polling) didn&#39;t seem to process events during some<br />humongous calculations.but i was relucatant to use CGUI coz A)i didn&#39;t want<br />to give away the gui system I had already pogrammed. B) I always have a do it all myself attitude.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
What are you asking for beyond general commentary on the concept of input buffers in general and/or the specific implementation in CGUI?
</p></div></div><p>

I just wanted anybody who know about CGUI internals to comment.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
What&#39;s wrong with your current code? It appears to buffer mouse events fine.
</p></div></div><p>

So does that mean i can use this as a reliable buffer system if im not bothered of<br />the fact that &quot;The current system &quot;gives up&quot; (return and discard the event) when mouse_call() and key_call() race each other.&quot;<br />as audric said. (May be i could implement mutex later) or should i go for something else like pthread.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
The keyboard code isn&#39;t posted, but I presume it buffers those okay also.
</p></div></div><p>

Here it is
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">void</span> key_call<span class="k2">(</span><span class="k1">int</span> f<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">2</td><td>  <span class="k1">unsigned</span> <span class="k1">int</span> i<span class="k2">;</span></td></tr><tr><td class="number">3</td><td>&#160;</td></tr><tr><td class="number">4</td><td>   <span class="k1">if</span><span class="k2">(</span><span class="k2">(</span><span class="k2">(</span>buf.end<span class="k3">+</span><span class="n">1</span><span class="k2">)</span> <span class="k3">&amp;</span> <span class="n">255</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k2">(</span>buf.start<span class="k3">&amp;</span><span class="n">255</span><span class="k2">)</span><span class="k2">)</span></td></tr><tr><td class="number">5</td><td>    <span class="k1">return</span><span class="k2">;</span></td></tr><tr><td class="number">6</td><td>  i <span class="k3">=</span> buf.end<span class="k3">&amp;</span><span class="n">255</span><span class="k2">;</span></td></tr><tr><td class="number">7</td><td>&#160;</td></tr><tr><td class="number">8</td><td>  buf.lock<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">9</td><td>  <span class="k1">if</span><span class="k2">(</span>buf.lock <span class="k3">!</span><span class="k3">=</span> <span class="n">1</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">10</td><td>    buf.lock--<span class="k2">;</span></td></tr><tr><td class="number">11</td><td>    <span class="k1">return</span><span class="k2">;</span></td></tr><tr><td class="number">12</td><td>   <span class="k2">}</span></td></tr><tr><td class="number">13</td><td>&#160;</td></tr><tr><td class="number">14</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.type <span class="k3">=</span> <span class="n">1</span><span class="k2">;</span></td></tr><tr><td class="number">15</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.val <span class="k3">=</span> f<span class="k2">;</span></td></tr><tr><td class="number">16</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.ex1 <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">17</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.ex2 <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">18</td><td>   buf.queue<span class="k3">&lt;</span>i&gt;.ex3 <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td>   buf.end<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span> <span class="c">//changed it as orz said</span></td></tr><tr><td class="number">20</td><td>&#160;</td></tr><tr><td class="number">21</td><td>   buf.lock--<span class="k2">;</span> </td></tr><tr><td class="number">22</td><td><span class="k2">}</span></td></tr><tr><td class="number">23</td><td><a href="http://www.allegro.cc/manual/END_OF_FUNCTION" target="_blank"><span class="a">END_OF_FUNCTION</span></a><span class="k2">(</span>key_call<span class="k2">)</span></td></tr></tbody></table></div></div><p>

and it does work fine.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (dialmformartian)</author>
		<pubDate>Thu, 08 Feb 2007 18:27:36 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">dialmformartian said:</div><div class="quote"><p>
So does that mean i can use this as a reliable buffer system if im not bothered of<br />the fact that &quot;The current system &quot;gives up&quot; (return and discard the event) when mouse_call() and key_call() race each other.&quot;
</p></div></div><p>
The only severe problem was the array[256], fixed.</p><p>Your test code to show the internals is not thread safe, but it will only cause a problem when the buffer is getting full and the buffer&#39;s head starts biting its tail.<br />(It should behave like: &quot;lock, make a copy of the element, remove the element, unlock&quot; : afterwards, you have all the time you want to process the event)<br />IMO, don&#39;t bother. Increase the buffer to 512, 1024 or even more if you actually run into problems. (full buffer means missed events, anyway)</p><p>The problem I pointed should not happen often, but consequences on input should be VERY weird:<br />Missed event: if it&#39;s a key_up, key_down, or mouse butto, it will look like a stuck key.<br />It will also cause an earlier entry in the buffer to be considered new, and happen again. It will be very visible as the mouse will jerk away and come back, or a key you didn&#39;t press will happen to be stuck down.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
(May be i could implement mutex later) or should i go for something else like pthread.
</p></div></div><p>
In my example I took the mutex functions that are in the pthread library, but it doesn&#39;t mean you need to multi-thread - the allegro hooks should work fine.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Thu, 08 Feb 2007 20:05:10 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
but it doesn&#39;t mean you need to multi-thread - the allegro hooks should work fine
</p></div></div><p>

But allegro hooks are executed by threads other than the main one.</p><p>I would suggest to dialmformartian to use pthreads anyway. Multi-threading programming is quite tricky and sooner or later he will have untraceable problems.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Thu, 08 Feb 2007 20:20:24 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">axilmar said:</div><div class="quote"><p>
But allegro hooks are executed by threads other than the main one.
</p></div></div><p>
Yes, Allegro uses threads internally.<br />Why dedicate threads yourself if the API already does things right? (and dialmformartian uses it rather correctly)<br />My first hint was only to use to a reliable and standard mutex system : two functions, lock and unlock. Just surround the critical sections, the closer the better.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Thu, 08 Feb 2007 20:44:34 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Why dedicate threads yourself if the API already does things right?
</p></div></div><p>

I did not say that dialmformartian should use his own threads. I said that he should use critical sections to synchronize access to the shared variables because Allegro uses threads.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
My first hint was only to use to a reliable and standard mutex system : two functions, lock and unlock. Just surround the critical sections, the closer the better
</p></div></div><p>

Exactly.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Thu, 08 Feb 2007 21:29:41 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>On further thought:</p><p>1.  Threading/locking/mutexes/whatever:</p><p>So far as I can tell, the keyboard/mouse callbacks in Allegro are all executed from a single thread.  Thus, there is no benefit to adding mutexes or anything like that.  </p><p>Thus: don&#39;t use pthreads/whatever for this.  Use of platform-dependant or other-library-specific threading primitives is unnecessary and undesirable in this context.  Even the &quot;lock&quot; variable in the code is useless.  The only kind of thead-awareness needed is the the stuff alread there - the &quot;volatile&quot; keyword on the buffer variables and careful ordering of when buf.end and buf.start are incremented.  </p><p>2.  mouse_call:</p><p>dailmformation:<br />You&#39;re implementation is perfectly fine as is.  Here are a few things I would consider doing anyway, just because I think the resulting code easier to read or maintain or prettier or something.  <br />2a: eliminate the branches and temporary variables - they don&#39;t accomplish anything.  <br />this:
</p><div class="source-code snippet"><div class="inner"><pre>   <span class="k1">unsigned</span> <span class="k1">int</span> i, ex1 <span class="k3">=</span> <span class="n">0</span>, ex2 <span class="k3">=</span> <span class="n">0</span>, ex3 <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span>
  
   <span class="k1">if</span><span class="k2">(</span>f <span class="k3">&amp;</span> MOUSE_FLAG_MOVE<span class="k2">)</span> <span class="k2">{</span>
      ex1 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_x" target="_blank"><span class="a">mouse_x</span></a><span class="k2">;</span>
      ex2<span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_y" target="_blank"><span class="a">mouse_y</span></a><span class="k2">;</span>
   <span class="k2">}</span>
   <span class="k1">if</span><span class="k2">(</span>f <span class="k3">&amp;</span> MOUSE_FLAG_MOVE_Z<span class="k2">)</span>
      ex3 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_z" target="_blank"><span class="a">mouse_z</span></a><span class="k2">;</span>
</pre></div></div><p>
becomes this:<br /><span class="source-code">   <span class="k1">unsigned</span> <span class="k1">int</span> i<span class="k2">;</span></span><br />and this:
</p><div class="source-code snippet"><div class="inner"><pre>   buf.queue<span class="k3">&lt;</span>i&gt;.ex1 <span class="k3">=</span> ex1<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex2 <span class="k3">=</span> ex2<span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex3 <span class="k3">=</span> ex3<span class="k2">;</span>
</pre></div></div><p>
becomes this:
</p><div class="source-code snippet"><div class="inner"><pre>   buf.queue<span class="k3">&lt;</span>i&gt;.ex1 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_x" target="_blank"><span class="a">mouse_x</span></a><span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex2 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_y" target="_blank"><span class="a">mouse_y</span></a><span class="k2">;</span>
   buf.queue<span class="k3">&lt;</span>i&gt;.ex3 <span class="k3">=</span> <a href="http://www.allegro.cc/manual/mouse_z" target="_blank"><span class="a">mouse_z</span></a><span class="k2">;</span>
</pre></div></div><p>
2b. Make the size of the buf.queue array be a numerical constant (an enum or #define) instead of hardwired.  Do the same thing for the &quot;type&quot; values (currently 0 is mouse, 1 is keyboard - wrap those values in enums or #defined constants instead).  That way it&#39;s easier to change the values later if there is some need to do so.  <br />2c. So far as I can tell, there is no point to the use of buf.lock on windows (or, I suspect, any other Allegro platform).  You could remove it.  </p><p>3.  Buffered Input:</p><p>dialmformartian: Your main loop reading the callbacks looks correct.  I would suggest that that the next step be to add an interface/wrapper to hide/encapsulate the details of the buffer from the main loop or anything else that needs to read keyboard/mouse events.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Thu, 08 Feb 2007 22:33:14 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
So far as I can tell, the keyboard/mouse callbacks in Allegro are all executed from a single thread
</p></div></div><p>
<img src="http://www.allegro.cc/forums/smileys/embarassed.gif" alt=":-[" /> ouch... sorry for all the bad advice I gave
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Audric)</author>
		<pubDate>Thu, 08 Feb 2007 23:06:46 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
So far as I can tell, the keyboard/mouse callbacks in Allegro are all executed from a single thread. Thus, there is no benefit to adding mutexes or anything like that.
</p></div></div><p>

But that thread is a different one from the main thread. Adding a mutex would prevent synchronization problems between the main thread and the allegro input thread.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
You&#39;re implementation is perfectly fine as is.
</p></div></div><p>

Actually, it is not. There is a possibility that non valid data will be read from the buffer.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Fri, 09 Feb 2007 17:37:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p><span class="source-code">But that thread is a different one from the main thread. Adding a mutex would prevent synchronization problems between the main thread <span class="k1">and</span> the allegro input thread.</span><br />Each variable is written to by only one thread, all variables are volatile, and all writes are atomic.  Under these circumstances, buf.start and buf.end together act as a valid synchronization mechanism, and heavier weight thread synchronization objects are not needed.  You can of course use a mutex anyway, but since Allegro does not offer mutexes that would require addition library or platform dependent stuff complicating the build process and/or portability.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Actually, it is not. There is a possibility that non valid data will be read from the buffer.
</p></div></div><p>
That was fixed by moving buf.end++.  If you are saying that another issue exists, describe it more specifically.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Sat, 10 Feb 2007 01:36:37 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
and all writes are atomic.
</p></div></div><p>

No they are not atomic. A variable increment has 3 CPU instructions: a) load value to register, b) increase value, c) put value back to memory.</p><p>For example:</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">int</span> x <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span>
x<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span>
</pre></div></div><p>

becomes:</p><div class="source-code snippet"><div class="inner"><pre><span class="n">004113B5</span>  mov         eax,dword ptr <span class="k2">[</span>x<span class="k2">]</span> 
<span class="n">004113B8</span>  add         eax,<span class="n">1</span> 
<span class="n">004113BB</span>  mov         dword ptr <span class="k2">[</span>x<span class="k2">]</span>,eax
</pre></div></div><p>

(copied from the disassembly window of the VS debugger).
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Sat, 10 Feb 2007 20:45:32 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
No they are not atomic. A variable increment has 3 CPU instructions: a) load value to register, b) increase value, c) put value back to memory.
</p></div></div><p>
I was not refering to the whole read-modify-write aspect, only the write aspect.  ie the value is always either equal to what it is before the statement or after the statement, the write portion is never split into two like it could be for a 64 bit integer.  <br />edit: and, side note, I believe increment instructions on x86 accept memory parameters, though of course they don&#39;t on most RISC architectures
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Sun, 11 Feb 2007 01:33:34 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I was not refering to the whole read-modify-write aspect, only the write aspect. ie the value is always either equal to what it is before the statement or after the statement, the write portion is never split into two like it could be for a 64 bit integer.<br />edit: and, side note, I believe increment instructions on x86 accept memory parameters, though of course they don&#39;t on most RISC architectures
</p></div></div><p>

But the whole point is to make the whole thing deterministically safe. It&#39;s not a big deal to include pthreads in your source anyway.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Sun, 11 Feb 2007 19:57:36 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
But that thread is a different one from the main thread.
</p></div></div><p>
Depends on the system. Allegro can run single-threaded on Linux (AFAIK), and has to run single-threaded on DOS. And given that the current API will be wrapped around a new API in the future, you can&#39;t know how that&#39;ll do it either. It&#39;s not good practice to assume callbacks or timers are run from a seperate thread than your program.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Sun, 11 Feb 2007 20:06:31 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>where do i get pthread
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (dialmformartian)</author>
		<pubDate>Mon, 12 Feb 2007 12:26:16 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p><a href="http://sourceware.org/pthreads-win32/">Right here.</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Mon, 12 Feb 2007 13:11:16 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
But the whole point is to make the whole thing deterministically safe. It&#39;s not a big deal to include pthreads in your source anyway.
</p></div></div><p>

</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Depends on the system. Allegro can run single-threaded on Linux (AFAIK), and has to run single-threaded on DOS. And given that the current API will be wrapped around a new API in the future, you can&#39;t know how that&#39;ll do it either. It&#39;s not good practice to assume callbacks or timers are run from a seperate thread than your program.
</p></div></div><p>

Sigh.  <br />Okay, let&#39;s this from three angles:<br />1.  Would adding a pthreads lock to the callback change anything on any specific platform?  <br />2.  Is this the manner in which Allegro intends its callbacks to be used?  <br />3.  What is the cost of adding additional locking?  </p><p>Now, the answers for each question:<br />1.  Would adding a pthreads lock to the callbacks change anything on any specific platform?  <br />In order for it to change something, the callback functions would have to be running concurrently with themselves on some platform.  This never happens on DOS, Windows, or Linux, the 3 platforms mentioned so far in this forum thread.  <br />DOS: the callbacks appears to happen from within an interrupt - ie with interrupts disabled so they cannot be interrupted.  <br />WIN32: the callbacks appear to be called from a single thread which does nothing but wait for input and call the callbacks when input arrives.  Since this is a single thread, it can&#39;t call another callback until the previous one returns.  <br />LINUX: the callbacks appear to occur inside the SIGIO handler.  According to the GNU docs, no signal handler is called during handling of the same signal, and since both keyboard and mouse use the same signal, neither keyboard nor mouse callbacks can run concurrently with themselves or each other.  </p><p>2.  Is this the manner in which Allegro intends its callbacks to be used?  <br />Allegro documentation says that the keyboard callback &quot;executes in an interrupt context&quot;.  It doesn&#39;t say that as DOS-specific, though obviously it&#39;s not literally true for non-DOS platforms.  For the mouse callback, all it says is &quot;function must be in locked memory, and must execute <u>very</u> quickly&quot;, even less helpful.  My interpretation is that this is the correct way to use the Allegro callbacks, though the documentation leaves this unfortunately ambiguous.  </p><p>3.  What is the cost of adding additional locking?  <br />If you use Allegro&#39;s built-in locking mechanisms (_enter_critical() and _exit_critical())... well, I don&#39;t know what the drawbacks are - Allegro&#39;s built-in locking mechanisms are undocumented so far as I can tell, so I presume you&#39;re not intended to use them for normal Allegro programs.  <br />If you use platform-specific locking mechanisms, the obvious cost is in portability.  <br />If you use pthreads or another threading API with implementations for a variety of platforms, the obvious cost is the standard cost for adding dependancies - it makes it harder for arbitrary Allegro users to get your code running - they have to get the library themselves, and figure out how to install it and link with it.  This cost is greatly reduced if you are the only one likely to compile your code.  (additionally, I suspect that using pthreads calls inside a DOS interrupt is a bad idea)</p><p>edit: note: this is only considering adding locking to the callback.  I would recommend adding locking to any function that reads from the input buffer if and only if your code is multithreaded independent of Allegro.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Mon, 12 Feb 2007 13:48:07 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>1. I don&#39;t believe pthreads EXISTS on DOS or DS.<br />2. You should never do anything clever in allegro timers. ever. You&#39;re just asking for trouble.<br />3. It just won&#39;t work on platforms without locking features.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Thomas Fjellstrom)</author>
		<pubDate>Mon, 12 Feb 2007 16:14:04 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Kitty Cat said:</div><div class="quote"><p>

Depends on the system. Allegro can run single-threaded on Linux (AFAIK), and has to run single-threaded on DOS.
</p></div></div><p>

If one is interested in running the program in DOS, then the app must be coded in a special way so as that DOS is handled appropriately. </p><p>It is not very difficult to use #ifdef to include different APIs according to platform.</p><div class="quote_container"><div class="title">Orz said:</div><div class="quote"><p>

Would adding a pthreads lock to the callback change anything on any specific platform?
</p></div></div><p>

Yes. It would make the program correct in those platforms that input is handled by a different thread.</p><div class="quote_container"><div class="title">Orz said:</div><div class="quote"><p>

Is this the manner in which Allegro intends its callbacks to be used?
</p></div></div><p>

Allegro has many DOSisms. Any modern library would not use the concept of interrupt to service input, but the concept of input queue. Unfortunately for us, Allegro does not do that, so there are two solutions:</p><p>1) fix Allegro to provide a mouse queue, like the keyboard queue.<br />2) use callbacks to implement your own queues.</p><p>I have done #2 in my GUI code.</p><div class="quote_container"><div class="title">Orz said:</div><div class="quote"><p>

What is the cost of adding additional locking?
</p></div></div><p>

It&#39;s minimal, because critical sections are used.</p><div class="quote_container"><div class="title">Orz said:</div><div class="quote"><p>

In order for it to change something, the callback functions would have to be running concurrently with themselves on some platform.
</p></div></div><p>

Nope, you got it wrong here. The lock will not synchronize the input threads, because there is only one input thread. The lock will synchronize the input thread and the main thread.</p><div class="quote_container"><div class="title">Orz said:</div><div class="quote"><p>

If you use Allegro&#39;s built-in locking mechanisms (_enter_critical() and _exit_critical())... well, I don&#39;t know what the drawbacks are - Allegro&#39;s built-in locking mechanisms are undocumented so far as I can tell, so I presume you&#39;re not intended to use them for normal Allegro programs.
</p></div></div><p>

Exactly.</p><div class="quote_container"><div class="title">Orz said:</div><div class="quote"><p>

If you use platform-specific locking mechanisms, the obvious cost is in portability.
</p></div></div><p>

It&#39;s no big deal to do so; just a couple of #ifdefs.</p><div class="quote_container"><div class="title">Orz said:</div><div class="quote"><p>

If you use pthreads or another threading API with implementations for a variety of platforms, the obvious cost is the standard cost for adding dependancies - it makes it harder for arbitrary Allegro users to get your code running - they have to get the library themselves, and figure out how to install it and link with it. This cost is greatly reduced if you are the only one likely to compile your code. (additionally, I suspect that using pthreads calls inside a DOS interrupt is a bad idea)
</p></div></div><p>

The cost of debugging multithreaded programs far outweights the cost of installing and linking with a library.</p><p><a href="http://www.flounder.com/badprogram.htm#beginthread">Here</a> is a very interesting link with the following quote:</p><p><b>No variable or structure should be accessed from multiple threads without being accessed in a thread-safe fashion.</b></p><p>Obviously the guy has great experience with threads and Windows, so if you don&#39;t accept my comment, please accept his.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Mon, 12 Feb 2007 18:24:05 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
If one is interested in running the program in DOS, then the app must be coded in a special way so as that DOS is handled appropriately.
</p></div></div><p>
Not if its coded properly. As long as you use Allegro properly, and don&#39;t rely on platform-specific behavior (eg. how callbacks are implemented), it&#39;ll work. However, people tend to become lax because &quot;it&#39;s not needed right now for my target platform(s)&quot; and thus don&#39;t bother with proper code.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
It is not very difficult to use #ifdef to include different APIs according to platform.
</p></div></div><p>
And given that this will be layered on top of the new API in the future, what&#39;ll you do if all platforms, instead of just DOS, are then more sensitive to improper code? You&#39;ll pretty much lock it out of being able to use the compatibility layer of newer versions and require Allegro 4.2 only.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Mon, 12 Feb 2007 18:37:36 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Not if its coded properly.
</p></div></div><p>

The only &#39;coded properly&#39; technique with multiple threads is to use synchronization. Didn&#39;t you read the link I posted?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Mon, 12 Feb 2007 20:43:00 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
The only &#39;coded properly&#39; technique with multiple threads is to use synchronization.
</p></div></div><p>
Yes, I fully agree with that. I&#39;m talking about Allegro&#39;s callbacks, though. <img src="http://www.allegro.cc/forums/smileys/tongue.gif" alt=":P" /> You can&#39;t assume whether Allegro&#39;s callbacks are threaded or not.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Mon, 12 Feb 2007 22:22:09 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
1. I don&#39;t believe pthreads EXISTS on DOS or DS.<br />2. You should never do anything clever in allegro timers. ever. You&#39;re just asking for trouble.<br />3. It just won&#39;t work on platforms without locking features.
</p></div></div><p>
1. <a href="http://moss.csc.ncsu.edu/~mueller/pthreads/">http://moss.csc.ncsu.edu/~mueller/pthreads/</a><br />2. I don&#39;t consider copying input to a buffer &quot;clever&quot;.  It&#39;s basically the ONLY thing that the input callbacks are useful for.  <br />3. edited: hm... It won&#39;t work correctly on platforms with sufficiently weak memory coherency models.  Investigating...</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
The cost of debugging multithreaded programs far outweights the cost of installing and linking with a library.Here [flounder.com] is a very interesting link with the following quote:</p><p>[bold]No variable or structure should be accessed from multiple threads without being accessed in a thread-safe fashion.[/bold]
</p></div></div><p>

You conspicuously omitted the next line &quot;Note that this applies only to variables where concurrent access can produce incorrect results&quot;.  He then links to an example of his where he recommends using just volatile variables.  <br />You might think that your position is vindicated by his next statement that incrementing a volatile integer is not thread-safe on a multi-CPU system.  However that statement does not apply to the special case where only one thread modifies a variable (while other thread(s) read it).  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Nope, you got it wrong here. The lock will not synchronize the input threads, because there is only one input thread. The lock will synchronize the input thread and the main thread.
</p></div></div><p>
There are three different locking scenarios we&#39;re looking at here in this thread:<br />locking type A: input callbacks lock to prevent reentry into the input callbacks<br />locking type B: input callbacks lock and input reader lock (same lock), to prevent reader from reading not-yet-ready events<br />locking type C: input readers lock (in a program with multiple threads, not counting those allegro created)</p><p>In that particular case, you were apparently talking about type B, while I was talking about type A.  It is my position that locking types A and B are pointless.  I think everyone is in agreement that type C is necessary if and only if the program is multithreaded (not counting Allegro-created threads that the user code knows nothing about).  </p><p>However, I&#39;m beginning to suspect that you might be right.  After reading through a bunch of x86, PPC, and C docs, it looks like the ordering may not be guaranteed between multiple CPUs under the circumstances in which the callbacks execute on various platforms unless extra effort is made.  That&#39;s somewhat scary though, as this appears to be what Allegro does internally... possibly I&#39;ve been up to long, but to my current interpretation, not only is this code slightly flawed in a multi-CPU environment, but so is Allegro keyboard handling on WIN32 and OSX.  And I&#39;m not too sure about the Linux version either... executing in the SIGIO handler protects it somewhat, but only if the reading thread is the original thread, and it can also execute in a timer callback instead, or from the main thread if simulate_keypress is called...  </p><p>Will think more tomorrow.  Hopefully.  </p><p>edit: fixed typo and changed #3 at the top
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Tue, 13 Feb 2007 03:56:42 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Yes, I fully agree with that. I&#39;m talking about Allegro&#39;s callbacks, though. <img src="http://www.allegro.cc/forums/smileys/tongue.gif" alt=":P" /> You can&#39;t assume whether Allegro&#39;s callbacks are threaded or not.
</p></div></div><p>

Well, if the game/library needs to behave correctly in the 90% of the computers out there (i.e. those that run Windows), you need to code threads properly.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
You conspicuously omitted the next line &quot;Note that this applies only to variables where concurrent access can produce incorrect results&quot;. He then links to an example of his where he recommends using just volatile variables.<br />You might think that your position is vindicated by his next statement that incrementing a volatile integer is not thread-safe on a multi-CPU system. However that statement does not apply to the special case where only one thread modifies a variable (while other thread(s) read it)
</p></div></div><p>

Incrementing an integer is not thread-safe, period. If you read the whole thing, you would have seen the analysis of the assembly code. </p><p>You are just asking for trouble especially when the integer is an index to a buffer.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
However, I&#39;m beginning to suspect that you might be right.
</p></div></div><p>

No sh1t, Sherlock! :-)</p><p>CPUs have gone multicore, you have forgotten that???
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Tue, 13 Feb 2007 18:07:37 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Incrementing an integer is not thread-safe, period. If you read the whole thing, you would have seen the analysis of the assembly code.
</p></div></div><p>
You seem to be ignoring the point of that: when a variable is only written to by one thread, the atomicity of the entire read-modify-write operation becomes irrelevant.  Only the atomicity of the write operation itself is relevant, because the variable cannot be modified asynchronously to that code (because only one thread modifies it).  And the write is generally atomic, provided that the integer is aligned (caveats: not true on 386sx when paired with a 32 bit compiler, some 8 bit CPU/compiler combinations, a few other arcane places... but to get even a remotely possible failure you have to find a platform that uses one of the handful of CPUs on which that&#39;s not true, uses multiple CPUs concurrently, and runs Allegro programs; you&#39;d have an easier time finding a system that uses 10 bit bytes).  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
You are just asking for trouble especially when the integer is an index to a buffer.
</p></div></div><p>
That is the part I&#39;m agreeing with now - that using the variable as an index into a changing buffer is unsafe.  According to my current understanding, this code has the capacity to return garbage input (though it almost never will).  It could be fixed with threading libraries, platform specific locking mechanisms, or more exotic coding methods.  However, I think that the Allegro internals have the same flaw in them, so you suffer from this flaw regardless...</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
CPUs have gone multicore, you have forgotten that???
</p></div></div><p>
I remembered the multicore part, but did not realize that Intel and others had weakened their memory coherency policies (I expected at least PRAM consistency for writes to volatile variables).  And I presumed that Allegro would arrange things in such a way that its input callbacks were usable in a safe manner without extra dependencies or extraordinary effort.  </p><p>edit:</p><p>ARRGHH!<br />Okay, I was too tired when coming to the conclusion that it wasn&#39;t safe.  x86 DOES still offer strong memory coherency, I misread the docs as saying the opposite of what they said.  Here&#39;s my current position (hopefully I will slow down the rate at which I change positions soon):</p><p>The code is correct on some platforms only.  <br />Allegro code is correct on some platforms only.  <br />Which platforms?  </p><p>x86/*: Allegro and this code both work, because of strong memory coherency guarantees on normal x86 systems.  </p><p>non-x86/linux: Allegro and this code <b>probably</b> work correctly, if the user code is totally single-threaded.  Merely having only one thread talk to allegro is not enough though - it must also be the thread that handles signals.  On x86 specifically the issue is (I think) irrelevant though because of the x86/* strong coherency guarantees.  However, the buf.lock mechanism should be kept, because in (very rare) cases the callback can become reentrant.  </p><p>PPC/macOSX: Allegro and this code are both incorrect on this platform.  </p><p>PPC/macOS9 and x86/DOS: Allegro and this code are correct, because (I think) the code all executes in interrupt context anyway.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Tue, 13 Feb 2007 19:33:35 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
That is the part I&#39;m agreeing with now - that using the variable as an index into a changing buffer is unsafe.
</p></div></div><p>

</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
ARRGHH!
</p></div></div><p>

You went into all this trouble just to prove what others said from the beginning? :-)
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (axilmar)</author>
		<pubDate>Thu, 15 Feb 2007 17:42:02 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
You went into all this trouble just to prove what others said from the beginning? :-)
</p></div></div><p>
And to submit a bug report : )</p><p>    <a href="http://www.allegro.cc/forums/thread/590120">http://www.allegro.cc/forums/thread/590120</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Sun, 18 Feb 2007 19:27:59 +0000</pubDate>
	</item>
</rss>
