Removing the contents of a Chan or MVar in a single discrete step

I'm writing a discrete simulation where request values from multiple threads accumulate in a centralized queue. Every n milliseconds, a manager wakes up to process requests. When the manager wakes up, it should retrieve all of the contents of the central queue in a single discrete step. While processing these, any client threads attempting to submit to the queue should block. When processing completes, the queue reopens and the manager goes back to sleep.

What's the best way to do this? The retry behavior of STM isn't really what I want. If I use a Chan or MVar, there's no way to prevent clients from enqueuing additional requests during processing. One approach is to use an MVar as a mutex on a Chan holding the queue. Are there other ways to do this?


I'd have to benchmark under your expected contention levels to know exactly what the best solution is, but here's my guess.

Use an MVar containing [Item] , whatever your item type is. Initialize the MVar with with newMVar [] . To add an element to the central list, use modifyMVar_ (return . (item :)) , where item is what you are adding to the list. Use takeMVar at the start of the processing pass, and putMVar [] and the end of it.

First, note that this isn't a queue, internally. If you want to handle things in the order they were added, reverse the list after extracting it.

Second, so long as these are the only operations you perform on the MVar , this is free of race conditions. That's because the MVar is initialized full, and each operation is "take the contents of the MVar , put something else in." Operations may block while waiting for the latter part of that, but this can't deadlock and there will be no lost updates.


Isn't there a problem with MVar [a] though? When there are no items to be read we want readers to be blocked, but since the MVar actually contains [] this doesn't happen.

链接地址: http://www.djcxy.com/p/81450.html

上一篇: 在Clojure中同步读取和写入的方式?

下一篇: 在单个离散步骤中移除Chan或MVar的内容