module Language.Futhark.Interpreter.FFI.AtomicList
  ( AtomicList,
    new,
    prepend,
    flush,
  )
where

import Data.IORef (IORef, atomicModifyIORef, newIORef)

newtype AtomicList v = AtomicList (IORef [v])

new :: IO (AtomicList v)
new :: forall v. IO (AtomicList v)
new = IORef [v] -> AtomicList v
forall v. IORef [v] -> AtomicList v
AtomicList (IORef [v] -> AtomicList v) -> IO (IORef [v]) -> IO (AtomicList v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [v] -> IO (IORef [v])
forall a. a -> IO (IORef a)
newIORef []

prepend :: v -> AtomicList v -> IO ()
prepend :: forall v. v -> AtomicList v -> IO ()
prepend v
v (AtomicList IORef [v]
r) = IORef [v] -> ([v] -> ([v], ())) -> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef [v]
r (([v] -> ([v], ())) -> IO ()) -> ([v] -> ([v], ())) -> IO ()
forall a b. (a -> b) -> a -> b
$ (,()) ([v] -> ([v], ())) -> ([v] -> [v]) -> [v] -> ([v], ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (v
v v -> [v] -> [v]
forall a. a -> [a] -> [a]
:)

flush :: AtomicList v -> IO [v]
flush :: forall v. AtomicList v -> IO [v]
flush (AtomicList IORef [v]
r) = IORef [v] -> ([v] -> ([v], [v])) -> IO [v]
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef [v]
r ([],)