Atomic.swift 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. //
  2. // Atomic.swift
  3. // ReactiveCocoa
  4. //
  5. // Created by Justin Spahr-Summers on 2014-06-10.
  6. // Copyright (c) 2014 GitHub. All rights reserved.
  7. //
  8. import Foundation
  9. /// An atomic variable.
  10. public final class Atomic<Value> {
  11. private var mutex = pthread_mutex_t()
  12. private var _value: Value
  13. /// Atomically get or set the value of the variable.
  14. public var value: Value {
  15. get {
  16. return withValue { $0 }
  17. }
  18. set(newValue) {
  19. modify { _ in newValue }
  20. }
  21. }
  22. /// Initialize the variable with the given initial value.
  23. ///
  24. /// - parameters:
  25. /// - value: Initial value for `self`.
  26. public init(_ value: Value) {
  27. _value = value
  28. let result = pthread_mutex_init(&mutex, nil)
  29. assert(result == 0, "Failed to initialize mutex with error \(result).")
  30. }
  31. deinit {
  32. let result = pthread_mutex_destroy(&mutex)
  33. assert(result == 0, "Failed to destroy mutex with error \(result).")
  34. }
  35. private func lock() {
  36. let result = pthread_mutex_lock(&mutex)
  37. assert(result == 0, "Failed to lock \(self) with error \(result).")
  38. }
  39. private func unlock() {
  40. let result = pthread_mutex_unlock(&mutex)
  41. assert(result == 0, "Failed to unlock \(self) with error \(result).")
  42. }
  43. /// Atomically replace the contents of the variable.
  44. ///
  45. /// - parameters:
  46. /// - newValue: A new value for the variable.
  47. ///
  48. /// - returns: The old value.
  49. public func swap(newValue: Value) -> Value {
  50. return modify { _ in newValue }
  51. }
  52. /// Atomically modify the variable.
  53. ///
  54. /// - parameters:
  55. /// - action: A closure that takes the current value.
  56. ///
  57. /// - returns: The old value.
  58. public func modify(@noescape action: (Value) throws -> Value) rethrows -> Value {
  59. return try withValue { value in
  60. _value = try action(value)
  61. return value
  62. }
  63. }
  64. /// Atomically perform an arbitrary action using the current value of the
  65. /// variable.
  66. ///
  67. /// - parameters:
  68. /// - action: A closure that takes the current value.
  69. ///
  70. /// - returns: The result of the action.
  71. public func withValue<Result>(@noescape action: (Value) throws -> Result) rethrows -> Result {
  72. lock()
  73. defer { unlock() }
  74. return try action(_value)
  75. }
  76. }