swift-nio-transport-services/Sources/NIOTransportServices/NIOTSEventLoopGroup.swift

85 lines
3.5 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
// swift-tools-version:4.0
//
// swift-tools-version:4.0
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import Foundation
import NIO
import NIOConcurrencyHelpers
import Dispatch
import Network
/// An `EventLoopGroup` containing `EventLoop`s specifically designed for use with
/// Network.framework's post-sockets networking API.
///
/// These `EventLoop`s provide highly optimised and powerful networking tools for
/// the Darwin platforms. They have a number of advantages over the regular
/// `SelectableEventLoop` that NIO uses on other platforms. In particular:
///
/// - The use of `DispatchQueue`s to schedule tasks allows the Darwin kernels to make
/// intelligent scheduling decisions, as well as to maintain QoS and ensure that
/// tasks required to handle networking in your application are given appropriate
/// priority by the system.
/// - Network.framework provides powerful tools for observing network state and managing
/// connections on devices with highly fluid networking environments, such as laptops
/// and mobile devices. These tools can be exposed to `Channel`s using this backend.
/// - Network.framework brings the networking stack into userspace, reducing the overhead
/// of most network operations by removing syscalls, and greatly increasing the safety
/// and security of the network stack.
/// - The applications networking needs are more effectively communicated to the kernel,
/// allowing mobile devices to change radio configuration and behaviour as needed to
/// take advantage of the various interfaces available on mobile devices.
///
/// In general, when building applications whose primary purpose is to be deployed on Darwin
/// platforms, the `NIOTSEventLoopGroup` should be preferred over the
/// `MultiThreadedEventLoopGroup`. In particular, on iOS, the `NIOTSEventLoopGroup` is the
/// preferred networking backend.
public final class NIOTSEventLoopGroup: EventLoopGroup {
private let index = Atomic<Int>(value: 0)
private let eventLoops: [NIOTSEventLoop]
public init(loopCount: Int = 1, defaultQoS: DispatchQoS = .default) {
precondition(loopCount > 0)
self.eventLoops = (0..<loopCount).map { _ in NIOTSEventLoop(qos: defaultQoS) }
}
public func next() -> EventLoop {
return self.eventLoops[abs(index.add(1) % self.eventLoops.count)]
}
/// Shuts down all of the event loops, rendering them unable to perform further work.
public func shutdownGracefully(queue: DispatchQueue, _ callback: @escaping (Error?) -> Void) {
let g = DispatchGroup()
let q = DispatchQueue(label: "nio.transportservices.shutdowngracefullyqueue", target: queue)
var error: Error? = nil
for loop in self.eventLoops {
g.enter()
loop.closeGently().mapIfError { err in
q.sync { error = err }
}.whenComplete { (_: Result<Void, Error>) in
g.leave()
}
}
g.notify(queue: q) {
callback(error)
}
}
public func makeIterator() -> EventLoopIterator {
return EventLoopIterator(self.eventLoops)
}
}