0001    /*
0002    * Sync (sync.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    * Portions of the documentation of this code are reproduced from 
0011    * work created and shared by Google and used according to terms 
0012    * described in the Creative Commons 3.0 Attribution License.
0013    *
0014    * http://golang.org/pkg/sync/
0015    */
0016    
0017    #if os(Linux)
0018    import Glibc
0019    #endif
0020    
0021    import Foundation
0022    
0023    /// The WaitResult enum is used as a return value by Mutex.wait()
0024    public enum WaitResult
sync.swift:109
    public func wait(timeout : NSTimeInterval = -1) -> WaitResult {
{ 0025 /// The wait resulted in a signal 0026 case Signaled
sync.swift:112
            return .Signaled
sync.swift:124
            return .Signaled
0027 /// The wait resulted in a timeout 0028 case TimedOut
sync.swift:126
        return .TimedOut
0029 } 0030 0031 /// A Mutex is a mutual exclusion lock. 0032 public class Mutex
atomic.swift:32
    private var mutex = Mutex()
chan.swift:13
private let idMutex = Mutex()
chan.swift:36
    internal let cond = Cond(Mutex())
select.swift:74
    var cond = Cond(Mutex())
select.swift:147
private let selectMutex = Mutex()
sync.swift:71
    public let mutex : Mutex
sync.swift:74
    public init(_ mutex : Mutex){
sync.swift:132
    private var mutex = Mutex()
sync.swift:167
    private var cond = Cond(Mutex())
{ 0033 private var mutex
sync.swift:36
        pthread_mutex_init(&mutex, nil)
sync.swift:39
        pthread_mutex_destroy(&mutex)
sync.swift:43
        pthread_mutex_lock(&mutex)
sync.swift:52
        pthread_mutex_unlock(&mutex)
sync.swift:111
            pthread_cond_wait(&cond, &mutex.mutex)
sync.swift:123
        if (pthread_cond_timedwait(&cond, &mutex.mutex, &ts) == 0) {
= pthread_mutex_t() 0034 /// Returns a new Mutex. 0035 public init
atomic.swift:32
    private var mutex = Mutex()
chan.swift:13
private let idMutex = Mutex()
chan.swift:36
    internal let cond = Cond(Mutex())
select.swift:74
    var cond = Cond(Mutex())
select.swift:147
private let selectMutex = Mutex()
sync.swift:132
    private var mutex = Mutex()
sync.swift:167
    private var cond = Cond(Mutex())
(){ 0036 pthread_mutex_init(&mutex, nil) 0037 } 0038 deinit{ 0039 pthread_mutex_destroy(&mutex) 0040 } 0041 /// Locks the mutex. If the lock is already in use, the calling operation blocks until the mutex is available. 0042 public func lock
atomic.swift:40
        mutex.lock()
atomic.swift:46
        mutex.lock()
atomic.swift:52
        atomic.mutex.lock()
atomic.swift:54
        mutex.lock()
atomic.swift:61
        mutex.lock()
atomic.swift:68
    lhs.mutex.lock()
atomic.swift:69
    if lhs !== rhs { rhs.mutex.lock() }
atomic.swift:72
    lhs.mutex.lock()
chan.swift:44
        idMutex.lock()
chan.swift:54
        cond.mutex.lock()
chan.swift:65
            cond.mutex.lock()
chan.swift:76
        cond.mutex.lock()
chan.swift:82
        cond.mutex.lock()
chan.swift:98
        cond.mutex.lock()
select.swift:35
            chan.cond.mutex.lock()
select.swift:42
            chan.cond.mutex.lock()
select.swift:121
            cond.mutex.lock()
select.swift:182
    selectMutex.lock()
sync.swift:58
        lock()
sync.swift:150
        mutex.lock()
sync.swift:181
        cond.mutex.lock()
sync.swift:199
        cond.mutex.lock()
(){ 0043 pthread_mutex_lock(&mutex) 0044 } 0045 /** 0046 Unlocks the mutex. It's an undefined error if mutex is not locked on entry to unlock. 0047 0048 A locked Mutex is not associated with a particular operation. 0049 It is allowed for one operation to lock a Mutex and then arrange for another operation to unlock it. 0050 */ 0051 public func unlock
atomic.swift:41
        defer { mutex.unlock() }
atomic.swift:47
        defer { mutex.unlock() }
atomic.swift:53
        defer { atomic.mutex.unlock() }
atomic.swift:55
        defer { mutex.unlock() }
atomic.swift:62
        defer { mutex.unlock() }
atomic.swift:75
    lhs.mutex.unlock()
atomic.swift:76
    if lhs !== rhs { rhs.mutex.unlock() }
atomic.swift:79
    lhs.mutex.unlock()
chan.swift:47
        idMutex.unlock()
chan.swift:55
        defer { cond.mutex.unlock() }
chan.swift:67
            cond.mutex.unlock()
chan.swift:77
        defer { cond.mutex.unlock() }
chan.swift:83
        defer { cond.mutex.unlock() }
chan.swift:99
        defer { cond.mutex.unlock() }
select.swift:36
            defer { chan.cond.mutex.unlock() }
select.swift:43
            defer { chan.cond.mutex.unlock() }
select.swift:123
            cond.mutex.unlock()
select.swift:186
    selectMutex.unlock()
sync.swift:60
        unlock()
sync.swift:151
        defer { mutex.unlock() }
sync.swift:182
        defer { cond.mutex.unlock() }
sync.swift:200
        defer { cond.mutex.unlock() }
sync.swift:204
        cond.mutex.unlock()
(){ 0052 pthread_mutex_unlock(&mutex) 0053 } 0054 0055 /// Locks the mutex before calling the function. Unlocks after closure is completed 0056 /// - Parameter: closure Closure function 0057 public func lock(closure : ()->()) { 0058 lock() 0059 closure() 0060 unlock() 0061 } 0062 } 0063 0064 /** 0065 `Cond` implements a condition variable, a rendezvous point for an operation waiting for or announcing the occurrence of an event. 0066 0067 Each `Cond` has an associated `Mutex`, which must be held when changing the condition and when calling the `wait` method. 0068 */ 0069 public class Cond
chan.swift:36
    internal let cond = Cond(Mutex())
chan.swift:39
    internal var gconds : [Cond] = []
select.swift:18
    func register(cond: Cond)
select.swift:19
    func unregister(cond: Cond)
select.swift:33
    func register(cond: Cond){
select.swift:40
    func unregister(cond: Cond){
select.swift:74
    var cond = Cond(Mutex())
sync.swift:167
    private var cond = Cond(Mutex())
{ 0070 private var cond
sync.swift:76
        pthread_cond_init(&cond, nil)
sync.swift:79
        pthread_cond_destroy(&cond)
sync.swift:83
        pthread_cond_broadcast(&cond)
sync.swift:87
        pthread_cond_signal(&cond)
sync.swift:111
            pthread_cond_wait(&cond, &mutex.mutex)
sync.swift:123
        if (pthread_cond_timedwait(&cond, &mutex.mutex, &ts) == 0) {
= pthread_cond_t() 0071 public let mutex
chan.swift:54
        cond.mutex.lock()
chan.swift:55
        defer { cond.mutex.unlock() }
chan.swift:65
            cond.mutex.lock()
chan.swift:67
            cond.mutex.unlock()
chan.swift:76
        cond.mutex.lock()
chan.swift:77
        defer { cond.mutex.unlock() }
chan.swift:82
        cond.mutex.lock()
chan.swift:83
        defer { cond.mutex.unlock() }
chan.swift:98
        cond.mutex.lock()
chan.swift:99
        defer { cond.mutex.unlock() }
select.swift:35
            chan.cond.mutex.lock()
select.swift:36
            defer { chan.cond.mutex.unlock() }
select.swift:42
            chan.cond.mutex.lock()
select.swift:43
            defer { chan.cond.mutex.unlock() }
select.swift:121
            cond.mutex.lock()
select.swift:123
            cond.mutex.unlock()
sync.swift:75
        self.mutex = mutex
sync.swift:111
            pthread_cond_wait(&cond, &mutex.mutex)
sync.swift:123
        if (pthread_cond_timedwait(&cond, &mutex.mutex, &ts) == 0) {
sync.swift:181
        cond.mutex.lock()
sync.swift:182
        defer { cond.mutex.unlock() }
sync.swift:199
        cond.mutex.lock()
sync.swift:200
        defer { cond.mutex.unlock() }
sync.swift:204
        cond.mutex.unlock()
: Mutex 0072 /// Returns a new Cond. 0073 /// - Parameter mutex: A Mutex object. 0074 public init
chan.swift:36
    internal let cond = Cond(Mutex())
select.swift:74
    var cond = Cond(Mutex())
sync.swift:167
    private var cond = Cond(Mutex())
(_ mutex : Mutex){ 0075 self.mutex = mutex 0076 pthread_cond_init(&cond, nil) 0077 } 0078 deinit { 0079 pthread_cond_destroy(&cond) 0080 } 0081 /// Wakes all operations waiting on `Cond`. 0082 public func broadcast
chan.swift:63
        cond.broadcast()
chan.swift:66
            cond.broadcast()
sync.swift:191
        cond.broadcast()
() { 0083 pthread_cond_broadcast(&cond) 0084 } 0085 /// Wakes one operations waiting on `Cond`. 0086 public func signal() { 0087 pthread_cond_signal(&cond) 0088 } 0089 /** 0090 0091 Atomically unlocks `.mutex` and suspends execution of the calling operation. 0092 After later resuming execution, `waita locks `.mutex' before returning. 0093 Unlike in other systems, `wait` cannot return unless awoken by `broadcast` or `signal', or the `timeout` param has been reached. 0094 0095 Because `.mutex` is not locked when 'wait first resumes, the caller typically cannot assume that the condition is true when `wait` returns. 0096 Instead, the caller should `wait` in a loop: 0097 0098 ``` 0099 cond.mutex.lock() 0100 while !condition() { 0101 cond.mutex.wait() 0102 } 0103 ... make use of condition ... 0104 cond.mutex.unlock() 0105 ``` 0106 */ 0107 /// - Parameter timeout: The length of time to wait. Default is forever. 0108 /// - Returns: WaitResult 0109 public func wait
chan.swift:94
            cond.wait()
chan.swift:112
            cond.wait()
select.swift:122
            cond.wait(0.25)
sync.swift:202
            cond.wait()
(timeout : NSTimeInterval = -1) -> WaitResult { 0110 if timeout < 0 { 0111 pthread_cond_wait(&cond, &mutex.mutex) 0112 return .Signaled 0113 } 0114 let timeInMs = Int(timeout * 1000) 0115 var tv = timeval() 0116 var ts = timespec() 0117 gettimeofday(&tv, nil) 0118 ts.tv_sec = time(nil) + timeInMs / 1000 0119 let intermediate = 1000 * 1000 * (timeInMs % 1000) 0120 ts.tv_nsec = Int(tv.tv_usec * 1000 + intermediate) 0121 ts.tv_sec += ts.tv_nsec / 1000000000 0122 ts.tv_nsec %= 1000000000 0123 if (pthread_cond_timedwait(&cond, &mutex.mutex, &ts) == 0) { 0124 return .Signaled 0125 } 0126 return .TimedOut 0127 } 0128 } 0129 0130 /// Once is an object that will perform exactly one action. 0131 public class Once { 0132 private var mutex
sync.swift:150
        mutex.lock()
sync.swift:151
        defer { mutex.unlock() }
= Mutex() 0133 private var oncer
sync.swift:152
        if oncer{
sync.swift:155
        oncer = true
= false 0134 /// Returns a new Once. 0135 public init() {} 0136 /** 0137 Calls the `action` if and only if `doit` is being called for the first time for this instance of `Once`. In other words, given 0138 0139 ``` 0140 var once Once 0141 ``` 0142 0143 If `doit` is called multiple times, only the first call will invoke `action`, even if `action` has a different value in each invocation. 0144 A new instance of `Once` is required for each function to execute. 0145 0146 This method is intended for initialization that must be run exactly once. 0147 */ 0148 /// - Parameter action: An action function. 0149 public func doit(action: ()->()) { 0150 mutex.lock() 0151 defer { mutex.unlock() } 0152 if oncer{ 0153 return 0154 } 0155 oncer = true 0156 action() 0157 } 0158 } 0159 0160 /** 0161 A WaitGroup waits for a collection of operations to finish. 0162 The main operation calls 'add' to set the number of operation to wait for. 0163 Then each of the operations runs and calls 'done' when finished. 0164 At the same time, 'wait' can be used to block until all operations have finished. 0165 */ 0166 public class WaitGroup { 0167 private var cond
sync.swift:181
        cond.mutex.lock()
sync.swift:182
        defer { cond.mutex.unlock() }
sync.swift:191
        cond.broadcast()
sync.swift:199
        cond.mutex.lock()
sync.swift:200
        defer { cond.mutex.unlock() }
sync.swift:202
            cond.wait()
sync.swift:204
        cond.mutex.unlock()
= Cond(Mutex()) 0168 private var count
sync.swift:183
        count += delta
sync.swift:184
        if count < 0 {
sync.swift:201
        while count > 0 {
= 0 0169 /// Returns a new WaitGroup. 0170 public init() {} 0171 /** 0172 Adds delta, which may be negative, to the WaitGroup counter. 0173 If the counter becomes Zero, all operations blocked on 'wait' are released. 0174 If the counter goes negative, 'add' fires a system exception. 0175 0176 Note that calls with a positive delta that occur when the counter is Zero must happen before a 'wait'. 0177 Calls with a negative delta, or calls with a positive delta that start when the counter is greater than zero, may happen at any time. 0178 Typically this means the calls to 'add' should execute before the statement creating the operation or other event to be waited for. 0179 */ 0180 public func add
sync.swift:195
        add(-1)
(delta: Int) { 0181 cond.mutex.lock() 0182 defer { cond.mutex.unlock() } 0183 count += delta 0184 if count < 0 { 0185 #if os(Linux) 0186 assertionFailure("negative WaitGroup counter") 0187 #else 0188 NSException.raise("Exception", format: "negative WaitGroup counter", arguments: getVaList([])) 0189 #endif 0190 } 0191 cond.broadcast() 0192 } 0193 /// Decrements the WaitGroup counter. 0194 public func done() { 0195 add(-1) 0196 } 0197 /// Blocks until the WaitGroup counter is Zero. 0198 public func wait() { 0199 cond.mutex.lock() 0200 defer { cond.mutex.unlock() } 0201 while count > 0 { 0202 cond.wait() 0203 } 0204 cond.mutex.unlock() 0205 } 0206 } 0207