--- /dev/null
+module ArrayQueue (
+ ArrayQueue, newArrayQueue,
+ aqEnqueue, aqIsEmpty, aqDequeue
+) where
+import Control.Monad.ST
+import Data.Array.ST
+import MonadStuff
+
+data ArrayQueue s = ArrayQueue {
+ aqArr :: STUArray s Int Int,
+ aqHeadI :: Int, -- Also used as an "end of queue" sentinel
+ aqTailI :: Int -- Element value can be aqHeadI; also used as a "not queued" sentinel
+}
+
+newArrayQueue :: (Int, Int) -> ST s (ArrayQueue s)
+newArrayQueue (lo, hi) = do
+ let headI = lo - 1
+ let tailI = lo - 2
+ arr <- newArray (tailI, hi) tailI
+ writeArray arr headI headI -- queue is empty
+ writeArray arr tailI headI -- tail is head
+ return $ ArrayQueue arr headI tailI
+
+aqEnqueue :: ArrayQueue s -> Int -> ST s Bool -- Was it added?
+aqEnqueue (ArrayQueue arr headI tailI) newI = do
+ newIval <- readArray arr newI
+ if newIval == tailI
+ then do
+ lst <- readArray arr tailI
+ writeArray arr lst newI -- Append newI.
+ writeArray arr newI headI -- newI is now the tail.
+ writeArray arr tailI newI -- The tail is now at newI.
+ return True
+ else return False -- Already on queue.
+
+aqIsEmpty :: ArrayQueue s -> ST s Bool
+aqIsEmpty (ArrayQueue arr headI tailI) = do
+ first <- readArray arr headI
+ return (first == headI)
+
+aqDequeue :: ArrayQueue s -> ST s (Maybe Int)
+aqDequeue (ArrayQueue arr headI tailI) = do
+ first <- readArray arr headI
+ if first == headI
+ then return Nothing
+ else do
+ next <- readArray arr first
+ writeArray arr headI next
+ if next == headI
+ then writeArray arr tailI headI -- Emptied queue.
+ else nop
+ writeArray arr first tailI -- No longer on queue.
+ return $ Just first