vcache-0.2.6: semi-transparent persistence for Haskell using LMDB, STM

Safe HaskellNone
LanguageHaskell2010

Database.VCache.PVar

Synopsis

Documentation

data PVar a Source

A PVar is a mutable variable backed by VCache. PVars can be read or updated transactionally (see VTx), and may store by reference as part of domain data (see VCacheable).

A PVar is not cached. If you want memory cached contents, you'll need a PVar that contains one or more VRefs. However, the first read from a PVar is lazy, so merely referencing a PVar does not require loading its contents into memory.

Due to how updates are batched, high frequency or bursty updates on a PVar should perform acceptably. Not every intermediate value is written to disk.

Anonymous PVars will be garbage collected if not in use. Persistence requires ultimately tying contents to named roots (cf. loadRootPVar). Garbage collection is based on reference counting, so developers must be cautious when working with cyclic data, i.e. break cycles before disconnecting them from root.

Note: PVars must never contain undefined or error values, nor any value that cannot be serialized by a VCacheable instance.

Instances

Eq (PVar a) 
Show (PVar a) 
VCacheable a => VCacheable (PVar a) 
Typeable (* -> *) PVar 

newPVar :: VCacheable a => a -> VTx (PVar a) Source

Create a new, anonymous PVar as part of an active transaction. Contents of the new PVar are not serialized unless the transaction commits (though a placeholder is still allocated).

newPVars :: VCacheable a => [a] -> VTx [PVar a] Source

Create an array of PVars with a given set of initial values. This is equivalent to `mapM newPVar`, but guarantees adjacent addresses in the persistence layer. This is mostly useful when working with large arrays, to simplify reasoning about paging performance.

newPVarIO :: VCacheable a => VSpace -> a -> IO (PVar a) Source

Create a new, anonymous PVar via the IO monad. This is similar to newTVarIO, but not as well motivated: global PVars should almost certainly be constructed as named, persistent roots.

newPVarsIO :: VCacheable a => VSpace -> [a] -> IO [PVar a] Source

Create an array of adjacent PVars via the IO monad.

loadRootPVar :: VCacheable a => VCache -> ByteString -> a -> PVar a Source

Global, persistent variables may be loaded by name. The name here is prefixed by vcacheSubdir to control namespace collisions between software components. These named variables are roots for GC purposes, and will not be deleted.

Conceptually, the root PVar has always been there. Loading a root is thus a pure computation. At the very least, it's an idempotent operation. If the PVar exists, its value is lazily read from the persistence layer. Otherwise, the given initial value is stored. To reset a root PVar, simply write before reading.

The recommended practice for roots is to use only a few of them for each persistent software component (i.e. each plugin, WAI app, etc.) similarly to how a module might use just a few global variables. If you need a dynamic set of variables, such as one per client, model that explicitly using anonymous PVars.

loadRootPVarIO :: VCacheable a => VCache -> ByteString -> a -> IO (PVar a) Source

Load a root PVar in the IO monad. This is convenient to control where errors are detected or when initialization is performed. See loadRootPVar.

readPVar :: PVar a -> VTx a Source

Read a PVar as part of a transaction.

readPVarIO :: PVar a -> IO a Source

Read a PVar in the IO monad.

This is more efficient than a full transaction. It simply peeks at the underlying TVar with readTVarIO. Durability of the value read is not guaranteed.

writePVar :: PVar a -> a -> VTx () Source

Write a PVar as part of a transaction.

modifyPVar :: PVar a -> (a -> a) -> VTx () Source

Modify a PVar.

modifyPVar' :: PVar a -> (a -> a) -> VTx () Source

Modify a PVar, strictly.

swapPVar :: PVar a -> a -> VTx a Source

Swap contents of a PVar for a new value.

pvar_space :: PVar a -> VSpace Source

virtual address space for PVar

unsafePVarAddr :: PVar a -> Address Source

Each PVar has a stable address in the VCache. This address will be very stable, but is not deterministic and isn't really something you should treat as meaningful information about the PVar. Mostly, this function exists to support hashtables or memoization with PVar keys.

The Show instance for PVars will also show the address.

unsafePVarRefct :: PVar a -> IO Int Source

This function allows developers to access the reference count for the PVar that is currently recorded in the database. This may be useful for heuristic purposes. However, caveats are needed:

First, because the VCache writer operates in a background thread, the reference count returned here may be slightly out of date.

Second, it is possible that VCache will eventually use some other form of garbage collection than reference counting. This function should be considered an unstable element of the API.

Root PVars start with one root reference.