Last active
August 29, 2015 14:15
-
-
Save insanehunter/ad7251c1f828db5f35c5 to your computer and use it in GitHub Desktop.
AccessibleOnQueue: Practical example of Applicative Functor to run composition of functions in background queue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Structure holding value that should be accessed and mutated on | |
/// some dispatch queue. | |
/// | |
/// Note: changing this to struct triggers a bug that 'forgets' mutations | |
public class AccessibleOnQueue<T> { | |
public init(_ value: T) { | |
_value = value | |
} | |
/// Creates a writer that can access and change stored value | |
public func mutate(f: (inout T) -> ()) -> WriteOnQueue { | |
return pure({ f(&self._value) }) | |
} | |
/// Creates a reader that can access stored value | |
public func get<U>(f: T -> U) -> ReadOnQueue<(), U> { | |
return pure({ f(self._value) }) | |
} | |
private var _value: T | |
} | |
/// Wrapper for read operation | |
public struct ReadOnQueue<T, U> { | |
public init(_ f: T -> U) { | |
self.mapping = f | |
} | |
private let mapping: T -> U | |
} | |
/// Wrapper for write operation | |
public struct WriteOnQueue { | |
public init(_ f: () -> ()) { | |
self.mutator = f | |
} | |
private let mutator: () -> () | |
} | |
/// Combining operator for reads. Produces a new operation that | |
/// performs combined read/transform on a value. | |
infix operator <*> { associativity left } | |
public func <*><T, U, V>(a: ReadOnQueue<T, U>, b: ReadOnQueue<U, V>) -> ReadOnQueue<T, V> { | |
return ReadOnQueue({ t in b.mapping(a.mapping(t)) }) | |
} | |
/// Combining operator for writes. Produces a new operation that | |
/// performs combined write/transform on a value. | |
public func <*>(a: WriteOnQueue, b: WriteOnQueue) -> WriteOnQueue { | |
return WriteOnQueue({ t in a.mutator(); b.mutator() }) | |
} | |
/// Lifting operator, creates read operation from a regular function on value. | |
public func pure<T, U>(f: T -> U) -> ReadOnQueue<T, U> { | |
return ReadOnQueue(f) | |
} | |
/// Lifting operator, creates write operation from a regular function on value. | |
public func pure(f: () -> ()) -> WriteOnQueue { | |
return WriteOnQueue(f) | |
} | |
/// Performs synchronous read operation on a given queue and returns resulting value. | |
public func readSync<U>(reader: ReadOnQueue<(), U>, # queue: dispatch_queue_t) -> U { | |
var value: U! | |
dispatch_sync(queue) { | |
value = reader.mapping() | |
} | |
return value | |
} | |
/// Performs asynchronous write operation on a given queue using write barrier. | |
public func writeAsync(writer: WriteOnQueue, # queue: dispatch_queue_t) { | |
dispatch_barrier_async(queue) { | |
writer.mutator() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage example: