lio-0.11.6.0: Labeled IO Information Flow Control Library

Safe HaskellTrustworthy
LanguageHaskell98

LIO.Concurrent.LMVar

Contents

Description

This module implements labeled MVars. The interface is analogous to Control.Concurrent.MVar, but the operations take place in the LIO monad. A labeled MVar, of type LMVar l a, is a mutable location that can be in one of two states; an LMVar can be empty, or it can be full (with a value of type a). The location is protected by a label of type l. As in the case of LIORefs (see LIO.LIORef), this label is fixed and does not change according to the content placed into the location. Unlike LIORefs, most operations use guardWrite or guardWriteP, reflecting the fact that there is no such thing as read-only or write-only operations on an LMVar.

LMVars can be used to build synchronization primitives and communication channels (LMVars themselves are single-place channels). We refer to Control.Concurrent.MVar for the full documentation on MVars.

Synopsis

Documentation

type LMVar l a = LObj l (MVar a) Source #

An LMVar is a labeled synchronization variable (an MVar) that can be used by concurrent threads to communicate.

Creating labeled MVars

newEmptyLMVar Source #

Arguments

:: Label l 
=> l

Label of LMVar

-> LIO l (LMVar l a)

New mutable location

Create a new labeled MVar, in an empty state. Note that the supplied label must be above the current label and below the current clearance. An exception will be thrown by the underlying guardAlloc if this is not the case.

newEmptyLMVarP :: PrivDesc l p => Priv p -> l -> LIO l (LMVar l a) Source #

Same as newEmptyLMVar except it takes a set of privileges which are accounted for in comparing the label of the MVar to the current label and clearance.

newLMVar Source #

Arguments

:: Label l 
=> l

Label of LMVar

-> a

Initial value of LMVar

-> LIO l (LMVar l a)

New mutable location

Create a new labeled MVar, in an filled state with the supplied value. Note that the supplied label must be above the current label and below the current clearance.

newLMVarP :: PrivDesc l p => Priv p -> l -> a -> LIO l (LMVar l a) Source #

Same as newLMVar except it takes a set of privileges which are accounted for in comparing the label of the MVar to the current label.

Take LMVar

takeLMVar :: Label l => LMVar l a -> LIO l a Source #

Return contents of the LMVar. Note that a take consists of a read and a write, since it observes whether or not the LMVar is full, and thus the current label must be the same as that of the LMVar (of course, this is not the case when using privileges). Hence, if the label of the LMVar is below the current clearance, we raise the current label to the join of the current label and the label of the MVar and read the contents of the MVar. The underlying guard guardWrite will throw an exception if any of the IFC checks fail. Finally, like MVars if the LMVar is empty, takeLMVar blocks.

takeLMVarP :: PrivDesc l p => Priv p -> LMVar l a -> LIO l a Source #

Same as takeLMVar except takeLMVarP takes a privilege object which is used when the current label is raised.

tryTakeLMVar :: Label l => LMVar l a -> LIO l (Maybe a) Source #

Non-blocking version of takeLMVar. It returns Nothing if the LMVar is empty, otherwise it returns Just value, emptying the LMVar.

tryTakeLMVarP :: PrivDesc l p => Priv p -> LMVar l a -> LIO l (Maybe a) Source #

Same as tryTakeLMVar, but uses priviliges when raising current label.

Put LMVar

putLMVar Source #

Arguments

:: Label l 
=> LMVar l a

Source LMVar

-> a

New value

-> LIO l () 

Puts a value into an LMVar. Note that a put consists of a read and a write, since it observes whether or not the LMVar is empty, and so the current label must be the same as that of the LMVar (of course, this is not the case when using privileges). As in the takeLMVar case, if the label of the LMVar is below the current clearance, we raise the current label to the join of the current label and the label of the MVar and put the value into the MVar. Moreover if these IFC restrictions fail, the underlying guardWrite throws an exception. If the LMVar is full, putLMVar blocks.

putLMVarP :: PrivDesc l p => Priv p -> LMVar l a -> a -> LIO l () Source #

Same as putLMVar except putLMVarP takes a privilege object which is used when the current label is raised.

Read LMVar

tryPutLMVar :: Label l => LMVar l a -> a -> LIO l Bool Source #

Non-blocking version of putLMVar. It returns True if the LMVar was empty and the put succeeded, otherwise it returns False.

tryPutLMVarP :: PrivDesc l p => Priv p -> LMVar l a -> a -> LIO l Bool Source #

Same as tryPutLMVar, but uses privileges when raising current label.

readLMVar :: Label l => LMVar l a -> LIO l a Source #

Combination of takeLMVar and putLMVar. Read the value, and just put it back. This operation is not atomic, and can can result in unexpected outcomes if another thread is simultaneously calling a function such as putLMVar, tryTakeLMVarP, or isEmptyLMVar for this LMVar.

readLMVarP :: PrivDesc l p => Priv p -> LMVar l a -> LIO l a Source #

Same as readLMVar except readLMVarP takes a privilege object which is used when the current label is raised.

Swap LMVar

swapLMVar Source #

Arguments

:: Label l 
=> LMVar l a

Source LMVar

-> a

New value

-> LIO l a

Taken value

Takes a value from an LMVar, puts a new value into the LMvar, and returns the taken value. Like the other LMVar operations it is required that the label of the LMVar be above the current label and below the current clearance. Moreover, the current label is raised to accommodate for the observation. The underlying guardWrite throws an exception if this cannot be accomplished. This operation is atomic iff there is no other thread calling putLMVar for this LMVar.

swapLMVarP :: PrivDesc l p => Priv p -> LMVar l a -> a -> LIO l a Source #

Same as swapLMVar except swapLMVarP takes a privilege object which is used when the current label is raised.

Check state of LMVar

isEmptyLMVar :: Label l => LMVar l a -> LIO l Bool Source #

Check the status of an LMVar, i.e., whether it is empty. The function succeeds if the label of the LMVar is below the current clearance -- the current label is raised to the join of the LMVar label and the current label.

isEmptyLMVarP :: PrivDesc l p => Priv p -> LMVar l a -> LIO l Bool Source #

Same as isEmptyLMVar, but uses privileges when raising current label.