{-# LANGUAGE DeriveDataTypeable, BangPatterns #-}------------------------------------------------------------------------------- |-- 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(openMemoryState)whereimportData.Acid.CoreimportData.Acid.CommonimportData.Acid.AbstractimportControl.Concurrent(newEmptyMVar,putMVar,MVar)importControl.Monad.State(runState)importData.ByteString.Lazy(ByteString)importData.Typeable(Typeable)importData.IORef(IORef,newIORef,readIORef,writeIORef)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).
-}dataMemoryStatest=MemoryState{localCore::Corest,localCopy::IORefst}deriving(Typeable)-- | Create an AcidState given an initial value.openMemoryState::(IsAcidicst)=>st-- ^ Initial state value.->IO(AcidStatest)openMemoryStateinitialState=docore<-mkCore(eventsToMethodsacidEvents)initialStateref<-newIORefinitialStatereturn$toAcidStateMemoryState{localCore=core,localCopy=ref}-- | 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-- @scheduleMemoryUpdate::UpdateEventevent=>MemoryState(EventStateevent)->event->IO(MVar(EventResultevent))scheduleMemoryUpdateacidStateevent=domvar<-newEmptyMVarmodifyCoreState_(localCoreacidState)$\st->dolet!(result,!st')=runStatehotMethodstwriteIORef(localCopyacidState)st'putMVarmvarresultreturnst'returnmvarwherehotMethod=lookupHotMethod(coreMethods(localCoreacidState))eventscheduleMemoryColdUpdate::MemoryStatest->TaggedByteString->IO(MVarByteString)scheduleMemoryColdUpdateacidStateevent=domvar<-newEmptyMVarmodifyCoreState_(localCoreacidState)$\st->dolet!(result,!st')=runStatecoldMethodstwriteIORef(localCopyacidState)st'putMVarmvarresultreturnst'returnmvarwherecoldMethod=lookupColdMethod(localCoreacidState)event-- | Issue a Query event and wait for its result. Events may be issued in parallel.memoryQuery::QueryEventevent=>MemoryState(EventStateevent)->event->IO(EventResultevent)memoryQueryacidStateevent=dost<-readIORef(localCopyacidState)let(result,_st)=runStatehotMethodstreturnresultwherehotMethod=lookupHotMethod(coreMethods(localCoreacidState))eventmemoryQueryCold::MemoryStatest->TaggedByteString->IOByteStringmemoryQueryColdacidStateevent=dost<-readIORef(localCopyacidState)let(result,_st)=runStatecoldMethodstreturnresultwherecoldMethod=lookupColdMethod(localCoreacidState)event-- | This is a nop with the memory backend.createMemoryCheckpoint::SafeCopyst=>MemoryStatest->IO()createMemoryCheckpointacidState=return()-- | This is a nop with the memory backend.createMemoryArchive::SafeCopyst=>MemoryStatest->IO()createMemoryArchiveacidState=return()-- | Close an AcidState and associated logs.-- Any subsequent usage of the AcidState will throw an exception.closeMemoryState::MemoryStatest->IO()closeMemoryStateacidState=closeCore(localCoreacidState)toAcidState::IsAcidicst=>MemoryStatest->AcidStatesttoAcidStatememory=AcidState{_scheduleUpdate=scheduleMemoryUpdatememory,scheduleColdUpdate=scheduleMemoryColdUpdatememory,_query=memoryQuerymemory,queryCold=memoryQueryColdmemory,createCheckpoint=createMemoryCheckpointmemory,createArchive=createMemoryArchivememory,closeAcidState=closeMemoryStatememory,acidSubState=mkAnyStatememory}