[Haskell-cafe] Re: how to implement daemon start and stop
ekirpichov at gmail.com
Fri Jan 23 04:50:46 EST 2009
2009/1/23 Ertugrul Soeylemez <es at ertes.de>:
> Luke Palmer <lrpalmer at gmail.com> wrote:
>> On Thu, Jan 22, 2009 at 9:04 AM, Ertugrul Soeylemez <es at ertes.de> wrote:
>> > Sometimes this is inevitable, but I've never seen a case, where
>> > IORefs couldn't be replaced by a more elegant State/StateT-based
>> > solution. And if you need to do multi-threading, Chans, MVars and
>> > semaphores are better anyway.
>> Please define "better". For the function in question, what advantages
>> do they give us?
> It gives you thread-safety for free, which IORefs don't give you. It's
> the same purpose, the same amount of code, but threadsafe by concept.
> Of course, for simple variables, IORefs will likely be thread-safe as
> well, but there is no guarantee here. With MVars you have that
>> 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
> What I'm saying is: Even if IORefs suffice, why would you want to use
> them, if MVar does the job as well and likely better?
>> > There is no reason to prefer an IORef over an MVar to signal
>> > something to another thread.
>> 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.
> Yes, that's a good point, but I think, you can safely disregard that for
> signalling a thread to quit.
>> > By the way, IORefs are by themselves not thread-safe. You need to
>> > use a special function, when using it in a multi-threaded manner.
>> You mean atomicModifyIORef?
>> IORefs *are* 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
>> x <- readIORef ref
>> writeIORef ref (x+1)
>> 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.
> That's exactly my point. In the above case they do just the same, but
> need more care.
>> And I will reiterate: *in this case* the use of IORef is fully
>> encapsulated in this function and *is threadsafe!* 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")
>> daemon :: IO () -> IO (IO ())
>> daemon action = do
>> stopvar <- newIORef False
>> let run = do
>> stop <- readIORef stopvar
>> if stop then return () else (action >> run)
>> forkIO run
>> return (writeIORef stopvar True)
> In this case, it's simply a coincidence that it's safe. It's because
> you're using an IORef Bool, and because writes to a Bool variable are
> atomic on virtually all platforms. An Integer may already fail to be
> thread-safe. You need more care and the payoff is zero. If you still
> insist on using IORefs, at least use the atomic function above, but that
> destroys the little performance benefit of using IORefs, unless GHC does
> some intelligent optimization here, which I doubt.
This would be the case if the IORef was unboxed, but it is boxed, so
writing an IORef is actually writing a pointer to a thunk; here, Bool
and Integer have no difference at all. However, I don't know whether
GHC makes pointer writes atomic on all platforms (Java does, so it's
at least doable).
> nightmare = unsafePerformIO (getWrongWife >>= sex)
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe