-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A safe approach to CAS and other atomic ops in Haskell.
--   
--   After GHC 7.4 a new `casMutVar#` primop became available, but it's
--   difficult to use safely, because pointer equality is a highly unstable
--   property in Haskell. This library provides a safer method based on the
--   concept of <a>Tickets</a>.
--   
--   Also, this library uses the "foreign primop" capability of GHC to add
--   access to other variants that may be of interest, specifically,
--   compare and swap inside an array.
--   
--   Note that as of GHC 7.8, the relevant primops have been included in
--   GHC itself. This library is engineered to work pre- and post-GHC-7.8,
--   while exposing the same interface.
@package atomic-primops
@version 0.8.4


-- | This module provides only the raw primops (and necessary types) for
--   atomic operations.
module Data.Atomics.Internal

-- | Given an array, an offset in machine words, the expected old value,
--   and the new value, perform an atomic compare and swap i.e. write the
--   new value if the current value matches the provided old value. Returns
--   the value of the element before the operation. Implies a full memory
--   barrier.
--   
--   <b><i>Warning:</i></b> this can fail with an unchecked exception.
casIntArray# :: MutableByteArray# d -> Int# -> Int# -> Int# -> State# d -> (# State# d, Int# #)

-- | Given an array, and offset in machine words, and a value to add,
--   atomically add the value to the element. Returns the value of the
--   element before the operation. Implies a full memory barrier.
--   
--   <b><i>Warning:</i></b> this can fail with an unchecked exception.
fetchAddIntArray# :: MutableByteArray# d -> Int# -> Int# -> State# d -> (# State# d, Int# #)
readForCAS# :: MutVar# RealWorld a -> State# RealWorld -> (# State# RealWorld, Ticket a #)
casMutVarTicketed# :: MutVar# RealWorld a -> Ticket a -> Ticket a -> State# RealWorld -> (# State# RealWorld, Int#, Ticket a #)

-- | Unsafe, machine-level atomic compare and swap on an element within an
--   Array.
casArrayTicketed# :: MutableArray# RealWorld a -> Int# -> Ticket a -> Ticket a -> State# RealWorld -> (# State# RealWorld, Int#, Ticket a #)

-- | When performing compare-and-swaps, the <i>ticket</i> encapsulates
--   proof that a thread observed a specific previous value of a mutable
--   variable. It is provided in lieu of the "old" value to
--   compare-and-swap.
--   
--   Design note: <a>Ticket</a>s exist to hide objects from the GHC
--   compiler, which can normally perform many optimizations that change
--   pointer equality. A Ticket, on the other hand, is a first-class object
--   that can be handled by the user, but will not have its pointer
--   identity changed by compiler optimizations (but will of course, change
--   addresses during garbage collection).
data Ticket a
ptrEq :: a -> a -> Bool
instance GHC.Show.Show (Data.Atomics.Internal.Ticket a)
instance GHC.Classes.Eq (Data.Atomics.Internal.Ticket a)


-- | Integer counters providing thread-safe, lock-free mutation functions.
--   
--   Atomic counters are represented by a single memory location, such that
--   built-in processor instructions are sufficient to perform
--   fetch-and-add or compare-and-swap.
--   
--   Remember, contention on such counters should still be minimized!
module Data.Atomics.Counter

-- | The type of mutable atomic counters.
data AtomicCounter

-- | Create a new counter initialized to the given value.
newCounter :: Int -> IO AtomicCounter

-- | You should not depend on this type. It varies between different
--   implementations of atomic counters.
type CTicket = Int

-- | Opaque tickets cannot be constructed, but they can be destructed into
--   values.
peekCTicket :: CTicket -> Int

-- | Compare and swap for the counter ADT. Similar behavior to
--   <a>casIORef</a>, in particular, in both success and failure cases it
--   returns a ticket that you should use for the next attempt. (That is,
--   in the success case, it actually returns the new value that you
--   provided as input, but in ticket form.)
casCounter :: AtomicCounter -> CTicket -> Int -> IO (Bool, CTicket)

-- | Increment the counter by a given amount. Returns the value AFTER the
--   increment (in contrast with the behavior of the underlying instruction
--   on architectures like x86.)
--   
--   Note that UNLIKE with boxed implementations of counters, where
--   increment is based on CAS, this increment is <i>O(1)</i>.
--   Fetch-and-add does not require a retry loop like CAS.
incrCounter :: Int -> AtomicCounter -> IO Int

-- | An alternate version for when you don't care about the old value.
incrCounter_ :: Int -> AtomicCounter -> IO ()

-- | Equivalent to <a>readCounterForCAS</a> followed by <a>peekCTicket</a>.
readCounter :: AtomicCounter -> IO Int

-- | Just like the <a>Data.Atomics</a> CAS interface, this routine returns
--   an opaque ticket that can be used in CAS operations. Except for the
--   difference in return type, the semantics of this are the same as
--   <a>readCounter</a>.
readCounterForCAS :: AtomicCounter -> IO CTicket

-- | Make a non-atomic write to the counter. No memory-barrier.
writeCounter :: AtomicCounter -> Int -> IO ()


-- | Provides atomic memory operations on IORefs and Mutable Arrays.
--   
--   Pointer equality need not be maintained by a Haskell compiler. For
--   example, Int values will frequently be boxed and unboxed, changing the
--   pointer identity of the thunk. To deal with this, the compare-and-swap
--   (CAS) approach used in this module is uses a <i>sealed</i>
--   representation of pointers into the Haskell heap (<tt>Tickets</tt>).
--   Currently, the user cannot coin new tickets, rather a <a>Ticket</a>
--   provides evidence of a past observation, and grants permission to make
--   a future change.
module Data.Atomics

-- | When performing compare-and-swaps, the <i>ticket</i> encapsulates
--   proof that a thread observed a specific previous value of a mutable
--   variable. It is provided in lieu of the "old" value to
--   compare-and-swap.
--   
--   Design note: <a>Ticket</a>s exist to hide objects from the GHC
--   compiler, which can normally perform many optimizations that change
--   pointer equality. A Ticket, on the other hand, is a first-class object
--   that can be handled by the user, but will not have its pointer
--   identity changed by compiler optimizations (but will of course, change
--   addresses during garbage collection).
data Ticket a

-- | A ticket contains or can get the usable Haskell value. This function
--   does just that.
peekTicket :: Ticket a -> a

-- | Ordinary processor load instruction (non-atomic, not implying any
--   memory barriers).
--   
--   The difference between this function and <a>readIORef</a>, is that it
--   returns a <i>ticket</i>, for use in future compare-and-swap
--   operations.
readForCAS :: IORef a -> IO (Ticket a)

-- | Performs a machine-level compare and swap (CAS) operation on an
--   <a>IORef</a>. Returns a tuple containing a <a>Bool</a> which is
--   <a>True</a> when a swap is performed, along with the most
--   <tt>current</tt> value from the <a>IORef</a>. Note that this differs
--   from the more common CAS behavior, which is to return the <i>old</i>
--   value before the CAS occured.
--   
--   The reason for the difference is the ticket API. This function always
--   returns the ticket that you should use in your next CAS attempt. In
--   case of success, this ticket corresponds to the <tt>new</tt> value
--   which you yourself installed in the <a>IORef</a>, whereas in the case
--   of failure it represents the preexisting value currently in the IORef.
--   
--   Note "compare" here means pointer equality in the sense of
--   <a>reallyUnsafePtrEquality#</a>. However, the ticket API absolves the
--   user of this module from needing to worry about the pointer equality
--   of their values, which in general requires reasoning about the details
--   of the Haskell implementation (GHC).
--   
--   By convention this function is strict in the "new" value argument.
--   This isn't absolutely necesary, but we think it's a bad habit to use
--   unevaluated thunks in this context.
casIORef :: IORef a -> Ticket a -> a -> IO (Bool, Ticket a)

-- | This variant takes two tickets, i.e. the <tt>new</tt> value is a
--   ticket rather than an arbitrary, lifted, Haskell value.
casIORef2 :: IORef a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)

-- | A drop-in replacement for <a>atomicModifyIORef</a> that optimistically
--   attempts to compute the new value and CAS it into place without
--   introducing new thunks or locking anything. Note that this is more
--   STRICT than its standard counterpart and will only place evaluated
--   (WHNF) values in the IORef.
--   
--   The upside is that sometimes we see a performance benefit. The
--   downside is that this version is speculative -- when it retries, it
--   must reexecute the compution.
atomicModifyIORefCAS :: IORef a -> (a -> (a, b)) -> IO b

-- | A simpler version that modifies the state but does not return
--   anything.
atomicModifyIORefCAS_ :: IORef t -> (t -> t) -> IO ()

-- | Compare-and-swap. Follows the same rules as <a>casIORef</a>, returning
--   the ticket for then next operation.
--   
--   By convention this is WHNF strict in the "new" value provided.
casArrayElem :: MutableArray RealWorld a -> Int -> Ticket a -> a -> IO (Bool, Ticket a)

-- | This variant takes two tickets: the <tt>new</tt> value is a ticket
--   rather than an arbitrary, lifted, Haskell value.
casArrayElem2 :: MutableArray RealWorld a -> Int -> Ticket a -> Ticket a -> IO (Bool, Ticket a)

-- | Ordinary processor load instruction (non-atomic, not implying any
--   memory barriers).
readArrayElem :: forall a. MutableArray RealWorld a -> Int -> IO (Ticket a)

-- | Compare and swap on word-sized chunks of a byte-array. For indexing
--   purposes the bytearray is treated as an array of words (<a>Int</a>s).
--   Note that UNLIKE <a>casIORef</a> and <tt>casArrayTicketed</tt>, this
--   does not need to operate on tickets.
--   
--   Further, this version always returns the <i>old value</i>, that was
--   read from the array during the CAS operation. That is, it follows the
--   normal protocol for CAS operations (and matches the underlying
--   instruction on most architectures).
--   
--   Implies a full memory barrier.
casByteArrayInt :: MutableByteArray RealWorld -> Int -> Int -> Int -> IO Int

-- | Atomically add to a word of memory within a <a>MutableByteArray</a>,
--   returning the value *before* the operation. Implies a full memory
--   barrier.
fetchAddIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int

-- | Atomically subtract to a word of memory within a
--   <a>MutableByteArray</a>, returning the value *before* the operation.
--   Implies a full memory barrier.
fetchSubIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int

-- | Atomically bitwise AND to a word of memory within a
--   <a>MutableByteArray</a>, returning the value *before* the operation.
--   Implies a full memory barrier.
fetchAndIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int

-- | Atomically bitwise NAND to a word of memory within a
--   <a>MutableByteArray</a>, returning the value *before* the operation.
--   Implies a full memory barrier.
fetchNandIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int

-- | Atomically bitwise OR to a word of memory within a
--   <a>MutableByteArray</a>, returning the value *before* the operation.
--   Implies a full memory barrier.
fetchOrIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int

-- | Atomically bitwise XOR to a word of memory within a
--   <a>MutableByteArray</a>, returning the value *before* the operation.
--   Implies a full memory barrier.
fetchXorIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int

-- | Like <a>readForCAS</a>, but for <a>MutVar#</a>.
readMutVarForCAS :: MutVar# RealWorld a -> IO (Ticket a)

-- | MutVar counterpart of <a>casIORef</a>.
--   
--   By convention this is WHNF strict in the "new" value provided.
casMutVar :: MutVar# RealWorld a -> Ticket a -> a -> IO (Bool, Ticket a)

-- | This variant takes two tickets, i.e. the <tt>new</tt> value is a
--   ticket rather than an arbitrary, lifted, Haskell value.
casMutVar2 :: MutVar# RealWorld a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)

-- | Memory barrier implemented by the GHC rts (see SMP.h).
--   storeLoadBarrier :: IO ()
--   
--   Memory barrier implemented by the GHC rts (see SMP.h). loadLoadBarrier
--   :: IO ()
--   
--   Memory barrier implemented by the GHC rts (see SMP.h). writeBarrier ::
--   IO ()
--   
--   Memory barrier implemented by the GHC rts (see SMP.h).
storeLoadBarrier :: IO ()

-- | Memory barrier implemented by the GHC rts (see SMP.h).
loadLoadBarrier :: IO ()

-- | Memory barrier implemented by the GHC rts (see SMP.h).
writeBarrier :: IO ()

-- | Atomically add to a word of memory within a <a>MutableByteArray</a>.
--   
--   This function returns the NEW value of the location after the
--   increment. Thus, it is a bit misnamed, and in other contexts might be
--   called "add-and-fetch", such as in GCC's
--   <tt>__sync_add_and_fetch</tt>.

-- | <i>Deprecated: Replaced by fetchAddIntArray which returns the OLD
--   value</i>
fetchAddByteArrayInt :: MutableByteArray RealWorld -> Int -> Int -> IO Int
