 	}
 
 	public func start(onReady: CommReadyCallback) -> Comm {
+		dispatch_group_enter(receivedValue)
 		v = nil
-		dispatch_group_enter(receivedValue)
-
-		let (sender, receiver) = ch.recv(onReady)
-		if let sender = sender {
+
+		func haveValue(v: V?) {
+			self.v = v
+			dispatch_group_leave(self.receivedValue)
+			onReady()
+		}
+
+		switch ch.recv(onReady) {
+		case let .Block(thread):
 			go {
-				let (v, _) = sender.recv()
-				self.v = v
-				dispatch_group_leave(self.receivedValue)
-				onReady()
-			}
-
-			return sender.comm
-
-		} else {
+				let (v, _) = thread.waitForSender()
+				haveValue(v)
+			}
+
+			return thread.comm
+
+		case let .FromSender(thread):
 			go {
-				let (v, _) = receiver!.waitForSender()
-				self.v = v
-				dispatch_group_leave(self.receivedValue)
-				onReady()
-			}
-
-			return receiver!.comm
+				let (v, _) = thread.recv()
+				haveValue(v)
+			}
+
+			return thread.comm
 		}
 	}
 


public protocol SelectableRecvChannel {
	associatedtype ValueType
	func recv(_: CommReadyCallback) -> (WaitForRecv<ValueType>?, WaitForSend<ValueType>?)
}

public protocol SelectableSendChannel {
	associatedtype ValueType
	func send(_: CommReadyCallback) -> (WaitForSend<ValueType>?, WaitForRecv<ValueType>?)
}

public struct ASyncRecv<V> {

}

extension chan: SelectableRecvChannel {
	public func recv(onReady: CommReadyCallback) -> Receive<V> {
		var action: Receive = .Block(WaitForSend<V>(syncedComm: SyncedComm<V>(onReady: onReady)))

		dispatch_sync(q) {
			switch (action, self.senders) {
			case let (.Block(thread), senders) where senders.count == 0:
				self.receivers.append(thread)
			default:
				let sender = self.senders.removeFirst()
				sender.comm.onReady(onReady)
				action = .FromSender(sender)
			}
		}

		return action
	}
}

extension chan: SelectableSendChannel {
	public func send(onReady: CommReadyCallback) -> Send<V> {
		var action: Send = .Block(WaitForRecv<V>(syncedComm: SyncedComm<V>(onReady: onReady)))

		dispatch_sync(q) {
			switch (action, self.receivers) {
			case let (.Block(thread), receivers) where receivers.count == 0:
				self.senders.append(thread)
			default:
				let receiver = self.receivers.removeFirst()
				receiver.comm.onReady(onReady)
				action = .ToReceiver(receiver)
			}
		}

		return action
	}
}

