├── .gitignore ├── .travis.yml ├── LICENSE ├── Package.swift ├── README.md └── Sources ├── Buffer.swift ├── DispatchError.swift ├── IOChannel.swift ├── Queue.swift └── Semaphore.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/xcode 2 | 3 | ### Xcode ### 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | .build/ 10 | build/ 11 | DerivedData 12 | Carthage/ 13 | Packages/ 14 | 15 | ## Various settings 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | 26 | ## Other 27 | *.xccheckout 28 | *.moved-aside 29 | *.xcuserstate 30 | *.xcscmblueprint 31 | XcodeDevelopment/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7.1 3 | env: 4 | global: 5 | - LC_CTYPE=en_US.UTF-8 6 | - LANG=en_US.UTF-8 7 | matrix: 8 | - DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="GrandCentralDispatch iOS" SDK=iphonesimulator9.1 9 | - DESTINATION="OS=8.2,name=iPhone 5" SCHEME="GrandCentralDispatch iOS" SDK=iphonesimulator9.1 10 | - DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="GrandCentralDispatch iOS" SDK=iphonesimulator9.1 11 | - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="GrandCentralDispatch iOS" SDK=iphonesimulator9.1 12 | - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="GrandCentralDispatch iOS" SDK=iphonesimulator9.1 13 | - DESTINATION="arch=x86_64" SCHEME="GrandCentralDispatch OSX" SDK=macosx10.11 14 | before_install: 15 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet 16 | # - xcrun instruments -w "iPhone 6 (8.1 Simulator)" || echo "Launched" 17 | script: 18 | - set -o pipefail 19 | - xcodebuild -version 20 | - xcodebuild -project GrandCentralDispatch.xcodeproj -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" 21 | -configuration Debug ONLY_ACTIVE_ARCH=NO GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES 22 | GCC_GENERATE_TEST_COVERAGE_FILES=YES test | xcpretty -c 23 | - xcodebuild -project GrandCentralDispatch.xcodeproj -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" 24 | -configuration Release ONLY_ACTIVE_ARCH=NO GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES 25 | GCC_GENERATE_TEST_COVERAGE_FILES=YES test | xcpretty -c 26 | after_success: 27 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Zewo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "GCD" 5 | ) 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Deprecated] GCD 2 | === 3 | 4 | [![Swift][swift-badge]][swift-url] 5 | [![Platform][platform-badge]][platform-url] 6 | [![License][mit-badge]][mit-url] 7 | [![Slack][slack-badge]][slack-url] 8 | 9 | **GCD** is a Grand Central Dispatch wrapper. 10 | 11 | ## Features 12 | 13 | - [x] Queues 14 | - [x] Semaphore 15 | - [x] IO Channel 16 | 17 | ## Installation 18 | 19 | ```swift 20 | import PackageDescription 21 | 22 | let package = Package( 23 | dependencies: [ 24 | .Package(url: "https://github.com/Zewo/GCD.git", majorVersion: 0, minor: 4) 25 | ] 26 | ) 27 | ``` 28 | 29 | ## Community 30 | 31 | [![Slack][slack-image]][slack-url] 32 | 33 | The entire Zewo code base is licensed under MIT. By contributing to Zewo you are contributing to an open and engaged community of brilliant Swift programmers. Join us on [Slack](http://slack.zewo.io) to get to know us! 34 | 35 | License 36 | ------- 37 | 38 | **GCD** is released under the MIT license. See LICENSE for details. 39 | 40 | [swift-badge]: https://img.shields.io/badge/Swift-3.0-orange.svg?style=flat 41 | [swift-url]: https://swift.org 42 | [platform-badge]: https://img.shields.io/badge/Platform-Linux-lightgray.svg?style=flat 43 | [platform-url]: https://swift.org 44 | [mit-badge]: https://img.shields.io/badge/License-MIT-blue.svg?style=flat 45 | [mit-url]: https://tldrlegal.com/license/mit-license 46 | [slack-image]: http://s13.postimg.org/ybwy92ktf/Slack.png 47 | [slack-badge]: https://zewo-slackin.herokuapp.com/badge.svg 48 | [slack-url]: http://slack.zewo.io 49 | 50 | -------------------------------------------------------------------------------- /Sources/Buffer.swift: -------------------------------------------------------------------------------- 1 | // GrandCentralDispatch.swift 2 | // 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2015 Zewo 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | import Foundation 26 | 27 | func bufferFromData(data: dispatch_data_t?) -> [Int8] { 28 | var dataBuffer: [Int8] = [] 29 | 30 | if let data = data { 31 | var buffer: UnsafePointer = nil 32 | var length: Int = 0 33 | let _ = dispatch_data_create_map(data, &buffer, &length) 34 | dataBuffer = [Int8](repeating: 0, count: length) 35 | memcpy(&dataBuffer, buffer, length) 36 | } 37 | 38 | return dataBuffer 39 | } -------------------------------------------------------------------------------- /Sources/DispatchError.swift: -------------------------------------------------------------------------------- 1 | // DispatchError.swift 2 | // 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2015 Zewo 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | import Foundation 26 | 27 | public struct DispatchError : ErrorProtocol, CustomStringConvertible { 28 | public let description: String 29 | 30 | init(_ description: String) { 31 | self.description = description 32 | } 33 | 34 | static func fromErrorNumber(errorNumber: Int32) -> DispatchError { 35 | return String(validatingUTF8: strerror(errorNumber)).map(DispatchError.init)! 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/IOChannel.swift: -------------------------------------------------------------------------------- 1 | // IOChannel.swift 2 | // 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2015 Zewo 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | import Foundation 26 | 27 | public enum IOChannelType { 28 | case Stream 29 | case RandomAccess 30 | 31 | private var value: dispatch_io_type_t { 32 | switch self { 33 | case .Stream: return DISPATCH_IO_STREAM 34 | case .RandomAccess: return DISPATCH_IO_RANDOM 35 | } 36 | } 37 | } 38 | 39 | public enum IOChannelCleanUpResult { 40 | case Success 41 | case Failure(error: ErrorProtocol) 42 | 43 | public func success(f: Void -> Void) { 44 | switch self { 45 | case Success: f() 46 | default: break 47 | } 48 | } 49 | 50 | public func failure(f: ErrorProtocol -> Void) { 51 | switch self { 52 | case Failure(let e): f(e) 53 | default: break 54 | } 55 | } 56 | } 57 | 58 | public enum IOChannelResult { 59 | case Success(done: Bool, data: [Int8]) 60 | case Canceled(data: [Int8]) 61 | case Failure(error: ErrorProtocol) 62 | 63 | public func success(f: (done: Bool, data: [Int8]) -> Void) { 64 | switch self { 65 | case Success(let done, let data): f(done: done, data: data) 66 | default: break 67 | } 68 | } 69 | 70 | public func failure(f: ErrorProtocol -> Void) { 71 | switch self { 72 | case Failure(let e): f(e) 73 | default: break 74 | } 75 | } 76 | 77 | public func canceled(f: (data: [Int8]) -> Void) { 78 | switch self { 79 | case Canceled(let data): f(data: data) 80 | default: break 81 | } 82 | } 83 | } 84 | 85 | public struct IOChannel { 86 | let channel: dispatch_io_t 87 | 88 | public init(type: IOChannelType, fileDescriptor: Int32, queue: Queue = defaultQueue, cleanupHandler: IOChannelCleanUpResult -> Void) { 89 | channel = dispatch_io_create(type.value, fileDescriptor, queue.queue) { errorNumber in 90 | if errorNumber == 0 { 91 | cleanupHandler(.Success) 92 | } else { 93 | let error = DispatchError.fromErrorNumber(errorNumber) 94 | cleanupHandler(.Failure(error: error)) 95 | } 96 | }! 97 | } 98 | 99 | public func read(offset: Int64 = 0, length: Int = Int.max, queue: Queue = defaultQueue, handler: IOChannelResult -> Void) { 100 | let mappedHandler = mapHandler(handler) 101 | dispatch_io_read(channel, offset, length, queue.queue, mappedHandler) 102 | } 103 | 104 | public func write(offset: Int64 = 0, length: Int = Int.max, queue: Queue = defaultQueue, data: [Int8], handler: IOChannelResult -> Void) { 105 | let data = dispatch_data_create(data, data.count, queue.queue, nil) 106 | let mappedHandler = mapHandler(handler) 107 | dispatch_io_write(channel, offset, data, queue.queue, mappedHandler) 108 | } 109 | 110 | private func mapHandler(handler: IOChannelResult -> Void) -> (done: Bool, data: dispatch_data_t!, errorNumber: Int32) -> Void { 111 | return { done, data, errorNumber in 112 | if errorNumber == ECANCELED { 113 | handler(.Canceled(data: bufferFromData(data))) 114 | } else if errorNumber != 0 { 115 | let error = DispatchError.fromErrorNumber(errorNumber) 116 | handler(.Failure(error: error)) 117 | } else { 118 | handler(.Success(done: done, data: bufferFromData(data))) 119 | } 120 | } 121 | } 122 | 123 | public func setLowWater(lowWater: Int) { 124 | dispatch_io_set_low_water(channel, lowWater) 125 | } 126 | 127 | public func setHighWater(highWater: Int) { 128 | dispatch_io_set_high_water(channel, highWater) 129 | } 130 | 131 | public var fileDescriptor: Int32 { 132 | return dispatch_io_get_descriptor(channel) 133 | } 134 | 135 | public func close() { 136 | dispatch_io_close(channel, DISPATCH_IO_STOP) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Sources/Queue.swift: -------------------------------------------------------------------------------- 1 | // Queue.swift 2 | // 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2015 Zewo 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | import Foundation 26 | 27 | public enum QualityOfServiceClass { 28 | case UserInteractive 29 | case UserInitiated 30 | case Default 31 | case Utility 32 | case Background 33 | 34 | private var value: qos_class_t { 35 | switch self { 36 | case UserInteractive: 37 | return QOS_CLASS_USER_INTERACTIVE 38 | case UserInitiated: 39 | return QOS_CLASS_USER_INITIATED 40 | case Default: 41 | return QOS_CLASS_DEFAULT 42 | case Utility: 43 | return QOS_CLASS_UTILITY 44 | case Background: 45 | return QOS_CLASS_BACKGROUND 46 | } 47 | } 48 | } 49 | 50 | public var mainQueue = Queue(queue: dispatch_get_main_queue()!) 51 | /// Work performed in this queue is interactive with the user. Such work is requested to run at high priority relative to other work on the system. Specifying this QOS class is a request to run with nearly all available system CPU and I/O bandwidth even under contention. This is not an energy-efficient QOS class to use for large tasks. The use of this QOS class should be limited to critical interaction with the user such as handling events on the main event loop, view drawing, animation, etc. 52 | public var userInteractiveQueue = getGlobalQueue(qualityOfServiceClass: .UserInteractive) 53 | /// Work performed in this queue is initiated by the user and the user is likely waiting for the results. Such work is requested to run at a priority below critical user-interactive work, but relatively higher than other work on the system. This is not an energy-efficient QOS class to use for large tasks and the use of this QOS class should be limited to operations where the user is immediately waiting for the results. 54 | public var userInitiatedQueue = getGlobalQueue(qualityOfServiceClass: .UserInitiated) 55 | /// A default queue used by the system in cases where more specific QOS class information is not available. Such work is requested to run at a priority below critical user-interactive and user-initiated work, but relatively higher than utility and background tasks. Threads created by pthread_create() without an attribute specifying a QOS class will default to QOS_CLASS_DEFAULT. This QOS class value is not intended to be used as a work classification, it should only be set when propagating or restoring QOS class values provided by the system. 56 | public var defaultQueue = getGlobalQueue(qualityOfServiceClass: .Default) 57 | /// Work performed in this queue may or may not be initiated by the user and the user is unlikely to be immediately waiting for the results. Such work is requested to run at a priority below critical user-interactive and user-initiated work, but relatively higher than low-level system maintenance tasks. The use of this QOS class indicates the work should be run in an energy and thermally-efficient manner. 58 | public var utilityQueue = getGlobalQueue(qualityOfServiceClass: .Utility) 59 | /// Work performed in this queue is not initiated by the user and the user may be unaware of the results. Such work is requested to run at a priority below other work. The use of this QOS class indicates the work should be run in the most energy and thermally-efficient manner. 60 | public var backgroundQueue = getGlobalQueue(qualityOfServiceClass: .Background) 61 | 62 | func getGlobalQueue(qualityOfServiceClass qos: QualityOfServiceClass) -> Queue { 63 | return Queue(queue: dispatch_get_global_queue(qos.value, 0)) 64 | } 65 | 66 | public enum QueueType { 67 | case Serial 68 | case Concurrent 69 | 70 | var value: dispatch_queue_attr_t! { 71 | switch self { 72 | case Serial: return DISPATCH_QUEUE_SERIAL 73 | case Concurrent: return DISPATCH_QUEUE_CONCURRENT 74 | } 75 | } 76 | } 77 | 78 | public struct Queue { 79 | let queue: dispatch_queue_t 80 | 81 | init(queue: dispatch_queue_t) { 82 | self.queue = queue 83 | } 84 | 85 | public init(label: String = "", type: QueueType = .Serial, qualityOfServiceClass qos: QualityOfServiceClass = .Default, relativePriority: Int32 = 0) { 86 | let attributes = dispatch_queue_attr_make_with_qos_class(type.value, qos.value, relativePriority) 87 | queue = dispatch_queue_create(label, attributes) 88 | } 89 | 90 | /** 91 | Submits a closure for asynchronous execution on a dispatch queue. 92 | 93 | The `async()` function is the fundamental mechanism for submitting closures to a dispatch queue. 94 | 95 | Calls to `async()` always return immediately after the closure has been submitted, and never wait for the closure to be invoked. 96 | 97 | The target queue determines whether the closure will be invoked serially or concurrently with respect to other closures submitted to that same queue. Serial queues are processed concurrently with respect to each other. 98 | 99 | :param: queue The target dispatch queue to which the closure is submitted. The system will hold a reference on the target queue until the closure has finished. The default parameter is the **default queue**. 100 | :param: closure The closure to submit to the target dispatch queue. 101 | */ 102 | public func async(closure: Void -> Void) { 103 | dispatch_async(queue, closure) 104 | } 105 | 106 | /** 107 | Submits a closure for synchronous execution on a dispatch queue. 108 | 109 | Submits a closure to a dispatch queue like `async()`, however `sync()` will not return until the closure has finished. 110 | 111 | Calls to `sync()` targeting the current queue will result in dead-lock. Use of `sync()` is also subject to the same multi-party dead-lock problems that may result from the use of a mutex. Use of `async()` is preferred. 112 | 113 | Unlike `async()`, no retain is performed on the target queue. Because calls to this function are synchronous, the `sync()` "borrows" the reference of the caller. 114 | 115 | As an optimization, `sync()` invokes the closure on the current thread when possible. 116 | 117 | :param: queue The target dispatch queue to which the closure is submitted. The default parameter is the **main queue**. 118 | :param: closure The closure to be invoked on the target dispatch queue. 119 | */ 120 | public func sync(closure: Void -> Void) { 121 | dispatch_sync(queue, closure) 122 | } 123 | 124 | public func after(time: Double, closure: Void -> Void) { 125 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64(time * Double(NSEC_PER_SEC))) 126 | dispatch_after(time, queue, closure) 127 | } 128 | } 129 | 130 | public func main() { 131 | dispatch_main() 132 | } 133 | -------------------------------------------------------------------------------- /Sources/Semaphore.swift: -------------------------------------------------------------------------------- 1 | // Semaphore.swift 2 | // 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2015 Zewo 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | import Foundation 26 | 27 | public struct Semaphore { 28 | let semaphore: dispatch_semaphore_t 29 | 30 | public init(resourceCount: Int) { 31 | semaphore = dispatch_semaphore_create(resourceCount)! 32 | } 33 | 34 | public func signal() { 35 | dispatch_semaphore_signal(semaphore) 36 | } 37 | 38 | public func wait(time: UInt64 = DISPATCH_TIME_FOREVER) { 39 | dispatch_semaphore_wait(semaphore, time) 40 | } 41 | } 42 | --------------------------------------------------------------------------------