Skip to content

Commit

Permalink
Added the ability for Atomics to support a hold pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
bencmorrison committed Jul 19, 2022
1 parent e3322b6 commit cf75ac9
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
45 changes: 45 additions & 0 deletions Sources/Atomic/Atomic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,49 @@ public struct Atomic<T> {
value = closure(value)
return value
}

/**
The `holdWhile(_:)` function uses a closure to allow operations to happen with
the Atomic value while preventing changes to the value.
- Parameter value: The current value of the wrapped value
*/
public typealias HoldClosure = (_ value: T) -> ()

/**
Allows you to hold the value of the Atomic object while the closure
is being executed. No changes to the value will happen.
- Parameter closure: The closure that is doing the work with the
value.
*/
public func holdWhile(_ closure: HoldClosure) {
lock.readLock()
defer { lock.unlock() }
closure(value)
}


private let holding = Holding()

/**
Allows the placement of an indefinate hold on the value while work is being done.
- Note: a `fatalError` will occure when a `hold()` is not matched with a `release()`
before another hold is called
- Returns: The current value
*/
@discardableResult
public mutating func hold() -> T {
lock.readLock()
guard holding.placeHold() else { fatalError("Atomic is already holding the value") }
return value
}

/**
Removes the placement of an indefinate hold on the value while work is being done.
- Note: a `fatalError` will occure when a `hold()` is not matched with a `release()`
before another hold is called
*/
public mutating func release() {
guard holding.removeHold() else { fatalError("Atomic is not already holding the value") }
lock.unlock()
}
}
31 changes: 31 additions & 0 deletions Sources/Atomic/Holding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// File.swift
//
//
// Created by Benjamin Morrison on 19/7/2022.
//

import Foundation

internal final class Holding {
private let lock = ReadWriteLock()
private var isHolding: Bool = false

func placeHold() -> Bool {
lock.writeLock()
defer { lock.unlock() }

guard !isHolding else { return false }
isHolding = true
return true
}

func removeHold() -> Bool {
lock.writeLock()
defer { lock.unlock() }

guard isHolding else { return false }
isHolding = false
return true
}
}

0 comments on commit cf75ac9

Please sign in to comment.