0001    /*
0002    * Select (select.swift) - Please be Safe
0003    *
0004    * Copyright (C) 2015 ONcast, LLC. All Rights Reserved.
0005    * Created by Josh Baker (joshbaker77@gmail.com)
0006    *
0007    * This software may be modified and distributed under the terms
0008    * of the MIT license.  See the LICENSE file for details.
0009    */
0010    
0011    #if os(Linux)
0012    import Glibc
0013    #endif
0014    
0015    import Foundation
0016    
0017    private protocol ItemAny
select.swift:24
private class Item<T> : ItemAny {
select.swift:75
    var items = [Int: ItemAny]()
select.swift:92
        var citems = [ItemAny]()
select.swift:98
        var ret : ItemAny?
{ 0018 func register
select.swift:100
            item.register(cond)
(cond: Cond) 0019 func unregister
select.swift:104
                item.unregister(cond)
(cond: Cond) 0020 func get
select.swift:112
                if item.get() {
() -> Bool; 0021 func call
select.swift:107
                item.call()
() 0022 } 0023 0024 private class Item
select.swift:81
        items[chan.id] = Item<T>(chan, block, nil)
select.swift:88
        items[0] = Item<Void>(nil, nil, block)
<T
select.swift:26
    var msg : T?
select.swift:27
    var chan : Chan<T>?
select.swift:28
    var caseBlock : ((T?)->())?
select.swift:30
    init(_ chan: Chan<T>?, _ caseBlock: ((T?)->())?, _ defBlock: (()->())?){
select.swift:30
    init(_ chan: Chan<T>?, _ caseBlock: ((T?)->())?, _ defBlock: (()->())?){
> : ItemAny { 0025 var closed
select.swift:57
                self.closed = closed
= false 0026 var msg
select.swift:56
                self.msg = msg
select.swift:65
            block(msg)
: T? 0027 var chan
select.swift:31
        (self.chan, self.caseBlock, self.defBlock) = (chan, caseBlock, defBlock)
select.swift:34
        if let chan = chan {
select.swift:41
        if let chan = chan {
select.swift:53
        if let chan = chan {
: Chan<T>? 0028 var caseBlock
select.swift:31
        (self.chan, self.caseBlock, self.defBlock) = (chan, caseBlock, defBlock)
select.swift:64
        if let block = caseBlock {
: ((T?)->())? 0029 var defBlock
select.swift:31
        (self.chan, self.caseBlock, self.defBlock) = (chan, caseBlock, defBlock)
select.swift:66
        } else if let block = defBlock {
: (()->())? 0030 init(_ chan: Chan<T>?, _ caseBlock: ((T?)->())?, _ defBlock: (()->())?){ 0031 (self.chan, self.caseBlock, self.defBlock) = (chan, caseBlock, defBlock) 0032 } 0033 func register(cond: Cond){ 0034 if let chan = chan { 0035 chan.cond.mutex.lock() 0036 defer { chan.cond.mutex.unlock() } 0037 chan.gconds += [cond] 0038 } 0039 } 0040 func unregister(cond: Cond){ 0041 if let chan = chan { 0042 chan.cond.mutex.lock() 0043 defer { chan.cond.mutex.unlock() } 0044 for i in 0..<chan.gconds.count { 0045 if chan.gconds[i] === cond { 0046 chan.gconds.removeAtIndex(i) 0047 return 0048 } 0049 } 0050 } 0051 } 0052 func get() -> Bool { 0053 if let chan = chan { 0054 let (msg, closed, ready) = chan.receive(false) 0055 if ready { 0056 self.msg = msg 0057 self.closed = closed 0058 return true 0059 } 0060 } 0061 return false 0062 } 0063 func call() { 0064 if let block = caseBlock { 0065 block(msg) 0066 } else if let block = defBlock { 0067 block() 0068 } 0069 } 0070 0071 } 0072 0073 private class ChanGroup
select.swift:148
private var selectStack : [ChanGroup] = []
select.swift:181
    let group = ChanGroup()
{ 0074 var cond
select.swift:100
            item.register(cond)
select.swift:104
                item.unregister(cond)
select.swift:121
            cond.mutex.lock()
select.swift:122
            cond.wait(0.25)
select.swift:123
            cond.mutex.unlock()
= Cond(Mutex()) 0075 var items
select.swift:78
        if items[chan.id] != nil {
select.swift:81
        items[chan.id] = Item<T>(chan, block, nil)
select.swift:85
        if items[0] != nil {
select.swift:88
        items[0] = Item<Void>(nil, nil, block)
select.swift:94
            if let item = items[ids[i]] {
select.swift:117
            if items[0] != nil {
select.swift:118
                ret = items[0]
= [Int: ItemAny]() 0076 var ids
select.swift:82
        ids.append(chan.id)
select.swift:91
        let rids = randomInts(ids.count)
select.swift:94
            if let item = items[ids[i]] {
= [Int]() 0077 func addCase
select.swift:194
        group.addCase(chan, block)
<T>(chan: Chan<T>, _ block: (T?)->()){ 0078 if items[chan.id] != nil { 0079 fatalError("selecting channel twice") 0080 } 0081 items[chan.id] = Item<T>(chan, block, nil) 0082 ids.append(chan.id) 0083 } 0084 func addDefault
select.swift:202
        group.addDefault(block)
(block: ()->()){ 0085 if items[0] != nil { 0086 fatalError("selecting default twice") 0087 } 0088 items[0] = Item<Void>(nil, nil, block) 0089 } 0090 func select
select.swift:187
    group.select()
(){ 0091 let rids = randomInts(ids.count) 0092 var citems = [ItemAny]() 0093 for i in rids { 0094 if let item = items[ids[i]] { 0095 citems.append(item) 0096 } 0097 } 0098 var ret : ItemAny? 0099 for item in citems { 0100 item.register(cond) 0101 } 0102 defer { 0103 for item in citems { 0104 item.unregister(cond) 0105 } 0106 if let item = ret { 0107 item.call() 0108 } 0109 } 0110 while true { 0111 for item in citems { 0112 if item.get() { 0113 ret = item 0114 return 0115 } 0116 } 0117 if items[0] != nil { 0118 ret = items[0] 0119 return 0120 } 0121 cond.mutex.lock() 0122 cond.wait(0.25) 0123 cond.mutex.unlock() 0124 } 0125 } 0126 func randomInts
select.swift:91
        let rids = randomInts(ids.count)
(count : Int) -> [Int]{ 0127 var ints = [Int](count: count, repeatedValue:0) 0128 for i in 0..<count { 0129 ints[i] = i 0130 } 0131 for i in 0..<count { 0132 #if os(Linux) 0133 let r = Int(random()) % count 0134 #else 0135 let r = Int(arc4random()) % count 0136 #endif 0137 0138 let t = ints[i] 0139 ints[i] = ints[r] 0140 ints[r] = t 0141 } 0142 return ints 0143 } 0144 } 0145 0146 0147 private let selectMutex
select.swift:182
    selectMutex.lock()
select.swift:186
    selectMutex.unlock()
= Mutex() 0148 private var selectStack
select.swift:183
    selectStack += [group]
select.swift:185
    selectStack.removeLast()
select.swift:193
    if let group = selectStack.last{
select.swift:201
    if let group = selectStack.last{
: [ChanGroup] = [] 0149 /** 0150 A "select" statement chooses which of a set of possible send or receive operations will proceed. 0151 It looks similar to a "switch" statement but with the cases all referring to communication operations. 0152 0153 ``` 0154 var c1 Chan<String>() 0155 var c2 Chan<String>() 0156 0157 // Each channel will receive a value after some amount of time, to simulate e.g. blocking RPC operations executing in concurrent operations. 0158 dispatch { 0159 sleep(1) 0160 c1 <- "one" 0161 } 0162 dispatch { 0163 sleep(2) 0164 c2 <- "two" 0165 } 0166 0167 // We’ll use select to await both of these values simultaneously, printing each one as it arrives. 0168 for var i = 0; i < 2; i++ { 0169 _select { 0170 _case (msg1) { c1 in 0171 print("received", msg1) 0172 } 0173 _case (msg2) { c2 in 0174 print("received", msg2) 0175 } 0176 } 0177 } 0178 ``` 0179 */ 0180 public func _select(block: ()->()){ 0181 let group = ChanGroup() 0182 selectMutex.lock() 0183 selectStack += [group] 0184 block() 0185 selectStack.removeLast() 0186 selectMutex.unlock() 0187 group.select() 0188 } 0189 /** 0190 A "case" statement reads messages from a channel. 0191 */ 0192 public func _case<T>(chan: Chan<T>, block: (T?)->()){ 0193 if let group = selectStack.last{ 0194 group.addCase(chan, block) 0195 } 0196 } 0197 /** 0198 A "default" statement will run if the "case" channels are not ready. 0199 */ 0200 public func _default(block: ()->()){ 0201 if let group = selectStack.last{ 0202 group.addDefault(block) 0203 } 0204 } 0205 0206 0207