On Thu, Jan 22, 2009 at 9:04 AM, Ertugrul Soeylemez <span dir="ltr"><<a href="mailto:es@ertes.de">es@ertes.de</a>></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">> A program that needs only IORefs and is threadsafe is *good* style to<br>
> me, because it means all the state is well-encapsulated (if it<br>
> escaped, it would fail to be threadsafe).<br>
<br>
</div>That's not my point. The use of IORefs indicates an imperative<br>
programming style. </blockquote><div><br>Um, we were talking about IORefs vs. MVars or TVars. I thought we were already firmly in the imperative world. Nobody on this list will argue against a pure solution always being preferable. <br>
</div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> Sometimes this is inevitable, but I've never seen a<br>
case, where IORefs couldn't be replaced by a more elegant<br>
State/StateT-based solution. And if you need to do multi-threading,<br>
Chans, MVars and semaphores are better anyway. </blockquote><div><br>Please define "better". For the function in question, what advantages do they give us?<br><br>Just to be clear, I wouldn't dare argue that IORefs can do everything MVars and TVars can do. I'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'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. 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. 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. So it all comes down to invariants. IORefs have no synchronization concepts, so code like:<br>
<br> x <- readIORef ref<br> writeIORef ref (x+1)<br><br>Is not threadsafe by most standards. That doesn't mean IORefs themselves are not threadsafe, just that you have to be careful how you use them.<br><br>
And I will reiterate: <i>in this case</i> the use of IORef is fully encapsulated in this function and <i>is threadsafe!</i> 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. I don't think they deserve "bad style" sledgehammer. (An instance of "use the right tool for the job")<br>
<br><div style="font-family: courier new,monospace;">daemon :: IO () -> 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;"> stopvar <- newIORef False</span></font></div><div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;"> let run = do</span></font></div>
<div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;"> stop <- readIORef stopvar</span></font></div><div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;"> if stop then return () else (action >> run)</span></font></div>
<div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;"> forkIO run</span></font></div><div style="font-family: courier new,monospace;"><font size="2"><span style="font-size: 12px;"> return (writeIORef stopvar True)</span></font></div>
<br>Luke<br></div></div>