MVar

public final class MVar<A>

An MVar (pronounced “em-var”) is a synchronising variable, used for communication between concurrent threads. It can be thought of as a box, which may be empty or full.

An MVar<A> is mutable location that is either empty or contains a value of type A. It has two fundamental operations: put(_:) which fills an MVar if it is empty and blocks otherwise, and take() which empties an MVar if it is full and blocks otherwise. They can be used in multiple different ways:

  1. As synchronized mutable variables,
  2. As channels, with take() and put(_:) as receive and send, and
  3. As a binary semaphore MVar<Void>, with take() and put(_:) as wait and signal.
  • Create an MVar which is initially empty.

    Declaration

    Swift

    public init()
  • Create an MVar which contains the supplied value.

    Declaration

    Swift

    public convenience init(value: A)

    Parameters

    value

    initial value

  • Return the contents of the MVar. If the MVar is currently empty, take() will wait until it is full. After a take(), the MVar is left empty.

    See also

    read()

    There are two further important properties of take():

    • take() is single-wakeup. That is, if there are multiple threads blocked in take(), and the MVar becomes full, only one thread will be woken up. The runtime guarantees that the woken thread completes its take() operation.
    • When multiple threads are blocked on an MVar, they are woken up in FIFO order. This is useful for providing fairness properties of abstractions built using MVars.

    Declaration

    Swift

    public func take() -> A

    Return Value

    the contents of the MVar

  • Put a value into an MVar. If the MVar is currently full, put(_:) will wait until it becomes empty.

    There are two further important properties of put(_:):

    • put(_:) is single-wakeup. That is, if there are multiple threads blocked in put(_:), and the MVar becomes empty, only one thread will be woken up. The runtime guarantees that the woken thread completes its put(_:) operation.
    • When multiple threads are blocked on an MVar, they are woken up in FIFO order. This is useful for providing fairness properties of abstractions built using MVars.

    Declaration

    Swift

    public func put(_ value: A)

    Parameters

    value

    new value

  • Atomically read the contents of an MVar. If the MVar is currently empty, read() will wait until it is full. read() is guaranteed to receive the next put(_:).

    See also

    take()

    read() is multiple-wakeup, so when multiple readers are blocked on an MVar, all of them are woken up at the same time.

    Declaration

    Swift

    public func read() -> A

    Return Value

    the contents of the MVar

  • Take a value from an MVar, put a new value into the MVar and return the value taken. This function is atomic only if there are no other producers for this MVar.

    Declaration

    Swift

    public func swap(_ value: A) -> A

    Parameters

    value

    new value

    Return Value

    old value

  • A non-blocking version of take(). The tryTake() function returns immediately. After tryTake(), the MVar is left empty.

    See also

    take()

    Declaration

    Swift

    public func tryTake() -> A?

    Return Value

    .none if the MVar is empty, or .some(a) if the MVar was full with contents a.

  • A non-blocking version of put(_:). The tryPut(_:) function attempts to put the value a into the MVar.

    See also

    put(_:)

    Declaration

    Swift

    public func tryPut(_ value: A) -> Bool

    Return Value

    true if it was putted successful, or false otherwise.

  • Check whether a given MVar is empty.

    Note

    Notice that the boolean value returned is just a snapshot of the state of the MVar. By the time you get to react on its result, the MVar may have been filled (or emptied) - so be extremely careful when using this operation. Use tryTake(_:) instead if possible.

    Declaration

    Swift

    public var isEmpty: Bool { get }
  • with(_:) is an rethrows wrapper for operating on the contents of an MVar. This operation rethrow exception if f raise exception. It won’t replace the original contents of the MVar if an exception is raised. However, it is only atomic if there are no other producers for this MVar.

    Seealso

    modify_(_:) and modify(_:)

    Declaration

    Swift

    public func with<B>(_ f: (A) throws -> B) rethrows -> B

    Parameters

    f

    ƒ

    Return Value

    calculated ƒ(a)

  • A rethrow wrapper for modifying the contents of an MVar. Like with(_:), modify_(_:) won’t replace the original contents of the MVar if an exception is raised during the operation. This function is only atomic if there are no other producers for this MVar.

    See also

    with(_:) and modify(_:)

    Declaration

    Swift

    public func modify_(_ f: (A) throws -> A) rethrows

    Parameters

    f

    f

  • A slight variation on modify_(_:) that allows a value to be returned (b) in addition to the modified value of the MVar.

    See also

    with(_:) and modify_(_:)

    Declaration

    Swift

    public func modify<B>(_ f: (A) throws -> (A, B)) rethrows -> B

    Parameters

    f

    ƒ

    Return Value

    ƒ(a).1

  • A non-blocking version of read(). The tryRead() function returns immediately, with .none if the MVar was empty, or .some(a) if the MVar was full with contents a.

    See also

    read(_:)

    Declaration

    Swift

    public func tryRead() -> A?

    Return Value

    .none if the MVar is empty, or .some(a) if the MVar was full with contents a.