gameServer/Store.hs
author sheepluva
Sun, 06 Feb 2011 11:39:11 +0100
changeset 4929 3dca560e6510
parent 4905 7842d085acf4
child 4932 f11d80bac7ed
permissions -rw-r--r--
I need this export in order to not have the wrapper.c fail to find Game() on linux From this point on compilation and usage of library should work on linux, at least does for me :P
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4905
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     1
module Store(
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     2
    ElemIndex(),
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     3
    MStore(),
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     4
    IStore(),
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     5
    newStore,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     6
    addElem,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     7
    removeElem,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     8
    readElem,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
     9
    writeElem,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    10
    modifyElem,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    11
    elemExists,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    12
    firstIndex,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    13
    indicesM,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    14
    withIStore,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    15
    withIStore2,
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    16
    (!),
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    17
    indices
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    18
    ) where
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    19
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    20
import qualified Data.Array.IArray as IA
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    21
import qualified Data.Array.IO as IOA
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    22
import qualified Data.IntSet as IntSet
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    23
import Data.IORef
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    24
import Control.Monad
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    25
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    26
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    27
newtype ElemIndex = ElemIndex Int
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    28
    deriving (Eq, Show, Read, Ord)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    29
newtype MStore e = MStore (IORef (IntSet.IntSet, IntSet.IntSet, IOA.IOArray Int e))
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    30
newtype IStore e = IStore (IntSet.IntSet, IA.Array Int e)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    31
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    32
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    33
firstIndex :: ElemIndex
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    34
firstIndex = ElemIndex 0
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    35
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    36
-- MStore code
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    37
initialSize :: Int
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    38
initialSize = 10
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    39
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    40
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    41
growFunc :: Int -> Int
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    42
growFunc a = a * 3 `div` 2
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    43
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    44
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    45
newStore :: IO (MStore e)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    46
newStore = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    47
    newar <- IOA.newArray_ (0, initialSize - 1)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    48
    new <- newIORef (IntSet.empty, IntSet.fromAscList [0..initialSize - 1], newar)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    49
    return (MStore new)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    50
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    51
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    52
growStore :: MStore e -> IO ()
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    53
growStore (MStore ref) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    54
    (busyElems, freeElems, arr) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    55
    (_, m') <- IOA.getBounds arr
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    56
    let newM' = growFunc (m' + 1) - 1
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    57
    newArr <- IOA.newArray_ (0, newM')
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    58
    sequence_ [IOA.readArray arr i >>= IOA.writeArray newArr i | i <- [0..m']]
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    59
    writeIORef ref (busyElems, freeElems `IntSet.union` (IntSet.fromAscList [m'+1..newM']), newArr)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    60
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    61
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    62
growIfNeeded :: MStore e -> IO ()
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    63
growIfNeeded m@(MStore ref) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    64
    (_, freeElems, _) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    65
    when (IntSet.null freeElems) $ growStore m
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    66
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    67
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    68
addElem :: MStore e -> e -> IO ElemIndex
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    69
addElem m@(MStore ref) element = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    70
    growIfNeeded m
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    71
    (busyElems, freeElems, arr) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    72
    let (n, freeElems') = IntSet.deleteFindMin freeElems
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    73
    IOA.writeArray arr n element
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    74
    writeIORef ref (IntSet.insert n busyElems, freeElems', arr)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    75
    return $ ElemIndex n
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    76
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    77
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    78
removeElem :: MStore e -> ElemIndex -> IO ()
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    79
removeElem (MStore ref) (ElemIndex n) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    80
    (busyElems, freeElems, arr) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    81
    IOA.writeArray arr n (error $ "Store: no element " ++ show n)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    82
    writeIORef ref (IntSet.delete n busyElems, IntSet.insert n freeElems, arr)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    83
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    84
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    85
readElem :: MStore e -> ElemIndex -> IO e
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    86
readElem (MStore ref) (ElemIndex n) = readIORef ref >>= \(_, _, arr) -> IOA.readArray arr n
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    87
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    88
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    89
writeElem :: MStore e -> ElemIndex -> e -> IO ()
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    90
writeElem (MStore ref) (ElemIndex n) el = readIORef ref >>= \(_, _, arr) -> IOA.writeArray arr n el
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    91
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    92
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    93
modifyElem :: MStore e -> (e -> e) -> ElemIndex -> IO ()
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    94
modifyElem (MStore ref) f (ElemIndex n) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    95
    (_, _, arr) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    96
    IOA.readArray arr n >>= IOA.writeArray arr n . f
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    97
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    98
elemExists :: MStore e -> ElemIndex -> IO Bool
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
    99
elemExists (MStore ref) (ElemIndex n) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   100
    (_, free, _) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   101
    return $ n `IntSet.notMember` free
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   102
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   103
indicesM :: MStore e -> IO [ElemIndex]
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   104
indicesM (MStore ref) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   105
    (busy, _, _) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   106
    return $ map ElemIndex $ IntSet.toList busy
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   107
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   108
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   109
-- A way to see MStore elements in pure code via IStore
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   110
m2i :: MStore e -> IO (IStore e)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   111
m2i (MStore ref) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   112
    (a, _, c') <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   113
    c <- IOA.unsafeFreeze c'
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   114
    return $ IStore (a, c)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   115
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   116
i2m :: (MStore e) -> IStore e -> IO ()
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   117
i2m (MStore ref) (IStore (_, arr)) = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   118
    (b, e, _) <- readIORef ref
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   119
    a <- IOA.unsafeThaw arr
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   120
    writeIORef ref (b, e, a)
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   121
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   122
withIStore :: MStore e -> (IStore e -> a) -> IO a
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   123
withIStore m f = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   124
    i <- m2i m
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   125
    let res = f i
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   126
    res `seq` i2m m i
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   127
    return res
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   128
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   129
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   130
withIStore2 :: MStore e1 -> MStore e2 -> (IStore e1 -> IStore e2 -> a) -> IO a
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   131
withIStore2 m1 m2 f = do
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   132
    i1 <- m2i m1
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   133
    i2 <- m2i m2
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   134
    let res = f i1 i2
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   135
    res `seq` i2m m1 i1
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   136
    i2m m2 i2
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   137
    return res
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   138
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   139
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   140
-- IStore code
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   141
(!) :: IStore e -> ElemIndex -> e
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   142
(!) (IStore (_, arr)) (ElemIndex i) = (IA.!) arr i
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   143
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   144
indices :: IStore e -> [ElemIndex]
7842d085acf4 Fix merge :D
unc0rr
parents:
diff changeset
   145
indices (IStore (busy, _)) = map ElemIndex $ IntSet.toList busy