{-# LANGUAGE GADTs, OverloadedStrings, DeriveDataTypeable, TypeFamilies,
GeneralizedNewtypeDeriving, BangPatterns, CPP #-}------------------------------------------------------------------------------- |-- Module : Data.Acid.Memory-- Copyright : PublicDomain---- Maintainer : lemmih@gmail.com-- Portability : non-portable (uses GHC extensions)---- AcidState container without a transaction log. Mostly used for testing. --moduleData.Acid.Memory(IsAcidic(..),AcidState,Event(..),EventResult,EventState,UpdateEvent,QueryEvent,Update,Query,openAcidState,closeAcidState,createCheckpoint,createCheckpointAndClose,update,scheduleUpdate,query,update',query',runQuery)whereimportData.Acid.CoreimportData.Acid.CommonimportControl.Concurrent(newEmptyMVar,putMVar,takeMVar,MVar)importControl.Monad.State(runState)importControl.Monad.Trans(MonadIO(liftIO))importData.SafeCopy(SafeCopy(..)){-| State container offering full ACID (Atomicity, Consistency, Isolation and Durability)
guarantees.
[@Atomicity@] State changes are all-or-nothing. This is what you'd expect of any state
variable in Haskell and AcidState doesn't change that.
[@Consistency@] No event or set of events will break your data invariants.
[@Isolation@] Transactions cannot interfere with each other even when issued in parallel.
[@Durability@] Successful transaction are guaranteed to survive system failure (both
hardware and software).
-}dataAcidStatest=AcidState{localCore::Corest}-- | Issue an Update event and wait for its result. Once this call returns, you are-- guaranteed that the changes to the state are durable. Events may be issued in-- parallel.---- It's a run-time error to issue events that aren't supported by the AcidState.update::UpdateEventevent=>AcidState(EventStateevent)->event->IO(EventResultevent)updateacidStateevent=takeMVar=<<scheduleUpdateacidStateevent-- | Issue an Update event and return immediately. The event is not durable-- before the MVar has been filled but the order of events is honored.-- The behavior in case of exceptions is exactly the same as for 'update'.---- If EventA is scheduled before EventB, EventA /will/ be executed before EventB:---- @--do scheduleUpdate acid EventA-- scheduleUpdate acid EventB-- @scheduleUpdate::UpdateEventevent=>AcidState(EventStateevent)->event->IO(MVar(EventResultevent))scheduleUpdateacidStateevent=domvar<-newEmptyMVarmodifyCoreState_(localCoreacidState)$\st->dolet!(result,!st')=runStatehotMethodstputMVarmvarresultreturnst'returnmvarwherehotMethod=lookupHotMethod(coreMethods(localCoreacidState))event-- | Same as 'update' but lifted into any monad capable of doing IO.update'::(UpdateEventevent,MonadIOm)=>AcidState(EventStateevent)->event->m(EventResultevent)update'acidStateevent=liftIO(updateacidStateevent)-- | Issue a Query event and wait for its result. Events may be issued in parallel.query::QueryEventevent=>AcidState(EventStateevent)->event->IO(EventResultevent)queryacidStateevent=domvar<-newEmptyMVarwithCoreState(localCoreacidState)$\st->dolet(result,_st)=runStatehotMethodstputMVarmvarresulttakeMVarmvarwherehotMethod=lookupHotMethod(coreMethods(localCoreacidState))event-- | Same as 'query' but lifted into any monad capable of doing IO.query'::(QueryEventevent,MonadIOm)=>AcidState(EventStateevent)->event->m(EventResultevent)query'acidStateevent=liftIO(queryacidStateevent)-- | This is a nop with the memory backend.createCheckpoint::SafeCopyst=>AcidStatest->IO()createCheckpointacidState=return()-- | This is an alias for 'closeAcidState' when using the memory backend.createCheckpointAndClose::SafeCopyst=>AcidStatest->IO()createCheckpointAndClose=closeAcidState-- | Create an AcidState given an initial value.openAcidState::(IsAcidicst)=>st-- ^ Initial state value. ->IO(AcidStatest)openAcidStateinitialState=docore<-mkCore(eventsToMethodsacidEvents)initialStatereturnAcidState{localCore=core}-- | Close an AcidState and associated logs.-- Any subsequent usage of the AcidState will throw an exception.closeAcidState::AcidStatest->IO()closeAcidStateacidState=closeCore(localCoreacidState)