Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does reading a TChan result in blocking or polling?

Tags:

haskell

ghc

stm

First, some background. I want a queue which I would like to operate in one of two different modes. In the first mode, I want to be able retrieve an element if one exists in the queue but not to block if there is no element. In the second mode, I want to be able to block until the queue has an element. (I am aware that I could use a specialized mechanism for each mode, but I'd like to factor out some common code and thus it would be easiest if I could use the same mechanism for both modes of operation.)

I could use Chan, but according to the documentation I shouldn't use isEmptyChan because it is deprecated due to potential for deadlock. This leaves me with TChan. The tryReadTChan function gives me exactly what I want for the first mode (i.e. I can check whether an element is present without blocking) but I am not sure exactly what readTChan does. My mental model is that the atomically block will keep retrying until an element is present in the channel, which means it will busy loop wasting CPU cycles; this is unlike readChan (i.e., the non-STM version) which (if I understand correctly) will actually block execution of the thread until an element is available, as MVars are understood by the runtime threads scheduler.

So is TChan like Chan in that if I use readTChan the runtime is smart enough to not schedule the calling thread until a value is available? Or will it waste a lot of CPU cycles continually polling into a value arrives?

like image 375
Gregory Crosswhite Avatar asked Jan 27 '13 07:01

Gregory Crosswhite


2 Answers

STM blocking (via retry) behaves as if it retries the transaction immediately, but the implementation is smarter: Since STM keeps track of what variables you've read as the transaction goes on, it knows that the transaction will behave the same way as long as those variables have the same values. So when a transaction fails, it'll block (won't actually retry) until one of the variables you used has changed. In the case of TChans, that means it'll block until someone writes to the TChan.

I recommend Simon Marlow's slides on concurrent and parallel Haskell for a good introduction to STM (among other things).

like image 181
shachaf Avatar answered Nov 01 '22 04:11

shachaf


Your mental model has the right denotational semantics, but misses out on an operational optimization STM makes. When a transaction retries in STM, it blocks until some TVar it read from before the retry is changed. (And yes, TChan is implemented in terms of TVar.)

So executing a transaction has the same meaning as if the transaction was continually retrying - but the STM system is smart enough to not busy-loop if there's no chance of things going differently within the transaction.

like image 36
Carl Avatar answered Nov 01 '22 04:11

Carl