{-# LANGUAGE DeriveDataTypeable, BangPatterns #-}
module Data.Acid.Memory
( openMemoryState
) where
import Data.Acid.Core
import Data.Acid.Common
import Data.Acid.Abstract
import Control.Concurrent ( newEmptyMVar, putMVar, MVar )
import Control.Monad.State ( runState )
import Data.ByteString.Lazy ( ByteString )
import Data.Typeable ( Typeable )
import Data.IORef ( IORef, newIORef, readIORef, writeIORef )
import Data.SafeCopy ( SafeCopy(..) )
data MemoryState st
= MemoryState { localCore :: Core st
, localCopy :: IORef st
} deriving (Typeable)
openMemoryState :: (IsAcidic st)
=> st
-> IO (AcidState st)
openMemoryState initialState
= do core <- mkCore (eventsToMethods acidEvents) initialState
ref <- newIORef initialState
return $ toAcidState MemoryState { localCore = core, localCopy = ref }
scheduleMemoryUpdate :: UpdateEvent event => MemoryState (EventState event) -> event -> IO (MVar (EventResult event))
scheduleMemoryUpdate acidState event
= do mvar <- newEmptyMVar
modifyCoreState_ (localCore acidState) $ \st ->
do let !(result, !st') = runState hotMethod st
writeIORef (localCopy acidState) st'
putMVar mvar result
return st'
return mvar
where hotMethod = lookupHotMethod (coreMethods (localCore acidState)) event
scheduleMemoryColdUpdate :: MemoryState st -> Tagged ByteString -> IO (MVar ByteString)
scheduleMemoryColdUpdate acidState event
= do mvar <- newEmptyMVar
modifyCoreState_ (localCore acidState) $ \st ->
do let !(result, !st') = runState coldMethod st
writeIORef (localCopy acidState) st'
putMVar mvar result
return st'
return mvar
where coldMethod = lookupColdMethod (localCore acidState) event
memoryQuery :: QueryEvent event => MemoryState (EventState event) -> event -> IO (EventResult event)
memoryQuery acidState event
= do st <- readIORef (localCopy acidState)
let (result, _st) = runState hotMethod st
return result
where hotMethod = lookupHotMethod (coreMethods (localCore acidState)) event
memoryQueryCold :: MemoryState st -> Tagged ByteString -> IO ByteString
memoryQueryCold acidState event
= do st <- readIORef (localCopy acidState)
let (result, _st) = runState coldMethod st
return result
where coldMethod = lookupColdMethod (localCore acidState) event
createMemoryCheckpoint :: SafeCopy st => MemoryState st -> IO ()
createMemoryCheckpoint acidState
= return ()
createMemoryArchive :: SafeCopy st => MemoryState st -> IO ()
createMemoryArchive acidState
= return ()
closeMemoryState :: MemoryState st -> IO ()
closeMemoryState acidState
= closeCore (localCore acidState)
toAcidState :: IsAcidic st => MemoryState st -> AcidState st
toAcidState memory
= AcidState { _scheduleUpdate = scheduleMemoryUpdate memory
, scheduleColdUpdate = scheduleMemoryColdUpdate memory
, _query = memoryQuery memory
, queryCold = memoryQueryCold memory
, createCheckpoint = createMemoryCheckpoint memory
, createArchive = createMemoryArchive memory
, closeAcidState = closeMemoryState memory
, acidSubState = mkAnyState memory
}