Skip to content

Instantly share code, notes, and snippets.

@vittoriom
Last active January 24, 2016 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vittoriom/78be19521e327d578e61 to your computer and use it in GitHub Desktop.
Save vittoriom/78be19521e327d578e61 to your computer and use it in GitHub Desktop.
import Foundation
// Define here your domain-specific events
public enum MessageEvent {
case YourEvent
}
public protocol MessageProducer {
func addSubscriber(subscriber: MessageConsumer)
func removeSubscriber(subscriber: MessageConsumer)
func dispatchEvent(event: MessageEvent)
}
public protocol MessageConsumer: class {
func consumeEvent(event: MessageEvent)
}
public class MessageBus: MessageProducer {
private class WeakSubscriber {
weak var boxed: MessageConsumer?
init(subscriber: MessageConsumer) {
self.boxed = subscriber
}
}
private var subscribers: [WeakSubscriber] = []
private let lock: ReadWriteLock = PThreadReadWriteLock()
public static let sharedInstance = MessageBus()
public init() {}
private func cleanupNilSubscribers() {
lock.withWriteLock {
subscribers = subscribers.filter { $0.boxed != nil }
}
}
public func dispatchEvent(event: MessageEvent) {
cleanupNilSubscribers()
lock.withReadLock {
subscribers.forEach { subscriber in
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
subscriber.boxed?.consumeEvent(event)
}
}
}
}
public func addSubscriber(subscriber: MessageConsumer) {
lock.withWriteLock {
subscribers.append(WeakSubscriber(subscriber: subscriber))
}
cleanupNilSubscribers()
}
public func removeSubscriber(subscriber: MessageConsumer) {
lock.withWriteLock {
if let indexOfObject = subscribers.indexOf({ $0.boxed === subscriber }) {
subscribers.removeAtIndex(indexOfObject)
}
}
cleanupNilSubscribers()
}
}
// Original file can be found here https://github.com/bignerdranch/Deferred/blob/master/Sources/ReadWriteLock.swift
import Foundation
protocol ReadWriteLock {
func withReadLock<T>(@noescape body: () -> T) -> T
func withWriteLock<T>(@noescape body: () -> T) -> T
}
final class PThreadReadWriteLock: ReadWriteLock {
private var lock: UnsafeMutablePointer<pthread_rwlock_t>
init() {
lock = UnsafeMutablePointer.alloc(1)
let status = pthread_rwlock_init(lock, nil)
assert(status == 0)
}
deinit {
let status = pthread_rwlock_destroy(lock)
assert(status == 0)
lock.dealloc(1)
}
func withReadLock<T>(@noescape body: () -> T) -> T {
let result: T
pthread_rwlock_rdlock(lock)
result = body()
pthread_rwlock_unlock(lock)
return result
}
func withWriteLock<T>(@noescape body: () -> T) -> T {
let result: T
pthread_rwlock_wrlock(lock)
result = body()
pthread_rwlock_unlock(lock)
return result
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment