Skip to content

Instantly share code, notes, and snippets.

@dougmarcey
Created June 11, 2014 21:02
Show Gist options
  • Save dougmarcey/d0b40e6785f495a58c94 to your computer and use it in GitHub Desktop.
Save dougmarcey/d0b40e6785f495a58c94 to your computer and use it in GitHub Desktop.
//
// Goroutines.swift
// TestGoer
//
// Created by Doug Marcey on 6/11/14.
// Copyright (c) 2014 Doug Marcey. All rights reserved.
//
import Foundation
let NoWorkQueued = 0
let WorkQueued = 1
let SpaceAvailable = 0
let LimitReached = 1
class Channel<T> {
var items = T[]()
let queueLock = NSConditionLock(condition: NoWorkQueued)
let limitLock = NSConditionLock(condition: SpaceAvailable)
let limit: Int
init(limit:Int = 1) {
self.limit = limit
}
func append(item:T, timeout:Int = 3) {
if limitLock.lockWhenCondition(SpaceAvailable, beforeDate: NSDate(timeIntervalSinceNow: NSTimeInterval(timeout))) {
queueLock.lock()
items.append(item)
limitLock.unlockWithCondition(items.count == self.limit ? LimitReached : SpaceAvailable)
queueLock.unlockWithCondition(WorkQueued)
}
}
func shift(timeout:Int = 3) -> T? {
var item:T? = nil
if queueLock.lockWhenCondition(WorkQueued, beforeDate: NSDate(timeIntervalSinceNow: NSTimeInterval(timeout))) {
limitLock.lock()
item = items.removeAtIndex(0)
limitLock.unlockWithCondition(items.count == self.limit ? LimitReached : SpaceAvailable)
queueLock.unlockWithCondition((items.count > 0 ? WorkQueued : NoWorkQueued))
}
return item
}
}
operator infix <- {associativity right}
@infix func <-<T>(c:Channel<T>, item:T) -> Channel<T> {
c.append(item)
return c
}
operator prefix <- {}
@prefix func <-<T>(c: Channel<T>) -> T? {
return c.shift()
}
func go(routine :() -> ()) {
dispatch_async(dispatch_get_global_queue(0, 0)) {
routine()
go(routine)
}
}
func go(routine :() -> Any) {
dispatch_async(dispatch_get_global_queue(0, 0)) {
routine()
go(routine)
}
}
import Foundation
let c = Channel<String>()
let c2 = Channel<Int>()
var cc = 0
go {
if let i = <-c {
println(i)
c2 <- ++cc
}
}
go {
if let i = <-c2 {
println("Message " + String(i))
}
}
for i in 1..20 {
c <- "Hello " + String(i)
}
sleep(5)
func worker(done:Channel<Bool>) -> () -> () {
return {
println("Working...")
sleep(1)
println("Done")
done <- true
}
}
let done = Channel<Bool>()
go(worker(done))
<-done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment