Copyright | (c) 2016--2018 Michael Walker |
---|---|
License | MIT |
Maintainer | Michael Walker <mike@barrucadu.co.uk> |
Stability | experimental |
Portability | BangPatterns, GADTs, FlexibleContexts, LambdaCase, RecordWildCards |
Safe Haskell | None |
Language | Haskell2010 |
Operations over CRef
s and MVar
s. This module is NOT considered
to form part of the public interface of this library.
Relaxed memory operations over CRef
s are implemented with an
explicit write buffer: one per thread for TSO, and one per
thread/variable combination for PSO. Unsynchronised writes append
to this buffer, and periodically separate threads commit from these
buffers to the "actual" CRef
.
This model comes from /Dynamic Partial Order Reduction for Relaxed Memory Models/, N. Zhang, M. Kusano, and C. Wang (2015).
- newtype WriteBuffer n = WriteBuffer {}
- data BufferedWrite n where
- BufferedWrite :: ThreadId -> ModelCRef n a -> a -> BufferedWrite n
- emptyBuffer :: WriteBuffer n
- bufferWrite :: MonadConc n => WriteBuffer n -> (ThreadId, Maybe CRefId) -> ModelCRef n a -> a -> n (WriteBuffer n)
- commitWrite :: MonadConc n => WriteBuffer n -> (ThreadId, Maybe CRefId) -> n (WriteBuffer n)
- readCRef :: MonadConc n => ModelCRef n a -> ThreadId -> n a
- readForTicket :: MonadConc n => ModelCRef n a -> ThreadId -> n (ModelTicket a)
- casCRef :: MonadConc n => ModelCRef n a -> ThreadId -> ModelTicket a -> a -> n (Bool, ModelTicket a, n ())
- readCRefPrim :: MonadConc n => ModelCRef n a -> ThreadId -> n (a, Integer)
- writeImmediate :: MonadConc n => ModelCRef n a -> a -> n (n ())
- writeBarrier :: MonadConc n => WriteBuffer n -> n ()
- addCommitThreads :: WriteBuffer n -> Threads n -> Threads n
- commitThreadId :: ThreadId -> Maybe CRefId -> ThreadId
- delCommitThreads :: Threads n -> Threads n
- data Blocking
- data Emptying
- putIntoMVar :: MonadConc n => ModelMVar n a -> a -> Action n -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- tryPutIntoMVar :: MonadConc n => ModelMVar n a -> a -> (Bool -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- readFromMVar :: (MonadConc n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- tryReadFromMVar :: MonadConc n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- takeFromMVar :: (MonadConc n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- tryTakeFromMVar :: MonadConc n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- mutMVar :: MonadConc n => Blocking -> ModelMVar n a -> a -> (Bool -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- seeMVar :: MonadConc n => Emptying -> Blocking -> ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
Manipulating CRef
s
newtype WriteBuffer n Source #
In non-sequentially-consistent memory models, non-synchronised writes get buffered.
The CRefId
parameter is only used under PSO. Under TSO each
thread has a single buffer.
data BufferedWrite n where Source #
A buffered write is a reference to the variable, and the value to write. Universally quantified over the value type so that the only thing which can be done with it is to write it to the reference.
BufferedWrite :: ThreadId -> ModelCRef n a -> a -> BufferedWrite n |
emptyBuffer :: WriteBuffer n Source #
An empty write buffer.
bufferWrite :: MonadConc n => WriteBuffer n -> (ThreadId, Maybe CRefId) -> ModelCRef n a -> a -> n (WriteBuffer n) Source #
Add a new write to the end of a buffer.
commitWrite :: MonadConc n => WriteBuffer n -> (ThreadId, Maybe CRefId) -> n (WriteBuffer n) Source #
Commit the write at the head of a buffer.
readCRef :: MonadConc n => ModelCRef n a -> ThreadId -> n a Source #
Read from a CRef
, returning a newer thread-local non-committed
write if there is one.
readForTicket :: MonadConc n => ModelCRef n a -> ThreadId -> n (ModelTicket a) Source #
Read from a CRef
, returning a Ticket
representing the current
view of the thread.
casCRef :: MonadConc n => ModelCRef n a -> ThreadId -> ModelTicket a -> a -> n (Bool, ModelTicket a, n ()) Source #
Perform a compare-and-swap on a CRef
if the ticket is still
valid. This is strict in the "new" value argument.
readCRefPrim :: MonadConc n => ModelCRef n a -> ThreadId -> n (a, Integer) Source #
Read the local state of a CRef
.
writeImmediate :: MonadConc n => ModelCRef n a -> a -> n (n ()) Source #
Write and commit to a CRef
immediately, clearing the update map
and incrementing the write count.
writeBarrier :: MonadConc n => WriteBuffer n -> n () Source #
Flush all writes in the buffer.
addCommitThreads :: WriteBuffer n -> Threads n -> Threads n Source #
Add phantom threads to the thread list to commit pending writes.
delCommitThreads :: Threads n -> Threads n Source #
Remove phantom threads.
Manipulating MVar
s
putIntoMVar :: MonadConc n => ModelMVar n a -> a -> Action n -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ()) Source #
Put into a MVar
, blocking if full.
tryPutIntoMVar :: MonadConc n => ModelMVar n a -> a -> (Bool -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ()) Source #
Try to put into a MVar
, not blocking if full.
readFromMVar :: (MonadConc n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ()) Source #
Read from a MVar
, blocking if empty.
tryReadFromMVar :: MonadConc n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ()) Source #
Try to read from a MVar
, not blocking if empty.
takeFromMVar :: (MonadConc n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ()) Source #
Take from a MVar
, blocking if empty.
tryTakeFromMVar :: MonadConc n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ()) Source #
Try to take from a MVar
, not blocking if empty.