On Thu, Jan 22, 2009 at 9:04 AM, Ertugrul Soeylemez <span dir="ltr">&lt;<a href="mailto:es@ertes.de">es@ertes.de</a>&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">&gt; A program that needs only IORefs and is threadsafe is *good* style to<br>
&gt; me, because it means all the state is well-encapsulated (if it<br>
&gt; escaped, it would fail to be threadsafe).<br>
<br>
</div>That&#39;s not my point. &nbsp;The use of IORefs indicates an imperative<br>
programming style. </blockquote><div><br>Um, we were talking about IORefs vs. MVars or TVars.&nbsp; I thought we were already firmly in the imperative world.&nbsp; Nobody on this list will argue against a pure solution always being preferable.&nbsp; <br>
&nbsp;</div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&nbsp;Sometimes this is inevitable, but I&#39;ve never seen a<br>
case, where IORefs couldn&#39;t be replaced by a more elegant<br>
State/StateT-based solution. &nbsp;And if you need to do multi-threading,<br>
Chans, MVars and semaphores are better anyway. &nbsp;</blockquote><div><br>Please define &quot;better&quot;.&nbsp; For the function in question, what advantages do they give us?<br><br>Just to be clear, I wouldn&#39;t dare argue that IORefs can do everything MVars and TVars can do.&nbsp;&nbsp; I&#39;m just perplexed why you say MVars and TVars are better, when an IORef does the trick just fine for our function.<br>
<br><br><br> <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">There is no reason to<br>
prefer an IORef over an MVar to signal something to another thread.</blockquote><div><br>Well, I usually don&#39;t go here, but benchmarks show that IORefs are the fastest of any of the mutable variable primitives, by at least a factor of 2.&nbsp; I wish I remembered where I saw that. <br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
By the way, IORefs are by themselves not thread-safe. &nbsp;You need to use a<br>
special function, when using it in a multi-threaded manner.</blockquote><div><br>You mean atomicModifyIORef?<br><br>IORefs <i>are</i> thread-safe by themselves: you will not make your program segfault by using them in a multithreaded program.&nbsp; So it all comes down to invariants.&nbsp; IORefs have no synchronization concepts, so code like:<br>
<br>&nbsp;&nbsp;&nbsp; x &lt;- readIORef ref<br>&nbsp;&nbsp;&nbsp; writeIORef ref (x+1)<br><br>Is not threadsafe by most standards.&nbsp; That doesn&#39;t mean IORefs themselves are not threadsafe, just that you have to be careful how you use them.<br><br>
And I will reiterate:&nbsp; <i>in this case</i> the use of IORef is fully encapsulated in this function and <i>is threadsafe!</i>&nbsp; Which is the basis of my argument: in imperative code, when you can limit the scope of an IORef to a small abstraction that is threadsafe, there is no advantage of TVars or MVars over them.&nbsp; I don&#39;t think they deserve &quot;bad style&quot; sledgehammer.&nbsp; (An instance of &quot;use the right tool for the job&quot;)<br>
<br><div style="font-family: courier new,monospace;">daemon :: IO () -&gt; IO (IO ())</div><div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;">daemon action = do</span></font></div>

<div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;">&nbsp;&nbsp; &nbsp;stopvar &lt;- newIORef False</span></font></div><div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;">&nbsp;&nbsp; &nbsp;let run = do</span></font></div>

<div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stop &lt;- readIORef stopvar</span></font></div><div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if stop then return () else (action &gt;&gt; run)</span></font></div>

<div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;">&nbsp;&nbsp; &nbsp;forkIO run</span></font></div><div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;">&nbsp;&nbsp; &nbsp;return (writeIORef stopvar True)</span></font></div>
<br>Luke<br></div></div>