Coverage Report

Created: 2026-07-29 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/swift-nio/Sources/NIOPosix/PosixSingletons.swift
Line
Count
Source
1
//===----------------------------------------------------------------------===//
2
//
3
// This source file is part of the SwiftNIO open source project
4
//
5
// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors
6
// Licensed under Apache License v2.0
7
//
8
// See LICENSE.txt for license information
9
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
10
//
11
// SPDX-License-Identifier: Apache-2.0
12
//
13
//===----------------------------------------------------------------------===//
14
15
#if !os(WASI)
16
17
import NIOCore
18
19
extension NIOSingletons {
20
    /// A globally shared, lazily initialized ``MultiThreadedEventLoopGroup``  that uses `epoll`/`kqueue` as the
21
    /// selector mechanism.
22
    ///
23
    /// The number of threads is determined by `NIOSingletons/groupLoopCountSuggestion`.
24
0
    public static var posixEventLoopGroup: MultiThreadedEventLoopGroup {
25
0
        singletonMTELG
26
0
    }
27
28
    /// A globally shared, lazily initialized ``NIOThreadPool`` that can be used for blocking I/O and other blocking operations.
29
    ///
30
    /// The number of threads is determined by `NIOSingletons/blockingPoolThreadCountSuggestion`.
31
0
    public static var posixBlockingThreadPool: NIOThreadPool {
32
0
        globalPosixBlockingPool
33
0
    }
34
}
35
36
extension MultiThreadedEventLoopGroup {
37
    /// A globally shared, singleton ``MultiThreadedEventLoopGroup``.
38
    ///
39
    /// SwiftNIO allows and encourages the precise management of all operating system resources such as threads and file descriptors.
40
    /// Certain resources (such as the main `EventLoopGroup`) however are usually globally shared across the program. This means
41
    /// that many programs have to carry around an `EventLoopGroup` despite the fact they don't require the ability to fully return
42
    /// all the operating resources which would imply shutting down the `EventLoopGroup`. This type is the global handle for singleton
43
    /// resources that applications (and some libraries) can use to obtain never-shut-down singleton resources.
44
    ///
45
    /// Programs and libraries that do not use these singletons will not incur extra resource usage, these resources are lazily initialized on
46
    /// first use.
47
    ///
48
    /// The loop count of this group is determined by `NIOSingletons/groupLoopCountSuggestion`.
49
    ///
50
    /// - Note: Users who do not want any code to spawn global singleton resources may set
51
    ///         `NIOSingletons/singletonsEnabledSuggestion` to `false` which will lead to a forced crash
52
    ///         if any code attempts to use the global singletons.
53
    ///
54
0
    public static var singleton: MultiThreadedEventLoopGroup {
55
0
        NIOSingletons.posixEventLoopGroup
56
0
    }
57
}
58
59
// swift-format-ignore: DontRepeatTypeInStaticProperties
60
extension EventLoopGroup where Self == MultiThreadedEventLoopGroup {
61
    /// A globally shared, singleton ``MultiThreadedEventLoopGroup``.
62
    ///
63
    /// This provides the same object as ``MultiThreadedEventLoopGroup/singleton``.
64
0
    public static var singletonMultiThreadedEventLoopGroup: Self {
65
0
        MultiThreadedEventLoopGroup.singleton
66
0
    }
67
}
68
69
extension NIOThreadPool {
70
    /// A globally shared, singleton ``NIOThreadPool``.
71
    ///
72
    /// SwiftNIO allows and encourages the precise management of all operating system resources such as threads and file descriptors.
73
    /// Certain resources (such as the main ``NIOThreadPool``) however are usually globally shared across the program. This means
74
    /// that many programs have to carry around an ``NIOThreadPool`` despite the fact they don't require the ability to fully return
75
    /// all the operating resources which would imply shutting down the ``NIOThreadPool``. This type is the global handle for singleton
76
    /// resources that applications (and some libraries) can use to obtain never-shut-down singleton resources.
77
    ///
78
    /// Programs and libraries that do not use these singletons will not incur extra resource usage, these resources are lazily initialized on
79
    /// first use.
80
    ///
81
    /// The thread count of this pool is determined by `NIOSingletons/suggestedBlockingPoolThreadCount`.
82
    ///
83
    /// - Note: Users who do not want any code to spawn global singleton resources may set
84
    ///         `NIOSingletons/singletonsEnabledSuggestion` to `false` which will lead to a forced crash
85
    ///         if any code attempts to use the global singletons.
86
0
    public static var singleton: NIOThreadPool {
87
0
        NIOSingletons.posixBlockingThreadPool
88
0
    }
89
}
90
91
0
private let singletonMTELG: MultiThreadedEventLoopGroup = {
92
0
    guard NIOSingletons.singletonsEnabledSuggestion else {
93
0
        fatalError(
94
0
            """
95
0
            Cannot create global singleton MultiThreadedEventLoopGroup because the global singletons have been \
96
0
            disabled by setting  `NIOSingletons.singletonsEnabledSuggestion = false`
97
0
            """
98
0
        )
99
0
    }
100
0
    let threadCount = NIOSingletons.groupLoopCountSuggestion
101
0
    let group = MultiThreadedEventLoopGroup._makePerpetualGroup(
102
0
        threadNamePrefix: "NIO-SGLTN-",
103
0
        numberOfThreads: threadCount
104
0
    )
105
0
    _ = Unmanaged.passUnretained(group).retain()  // Never gonna give you up,
106
0
    return group
107
0
}()
108
109
0
private let globalPosixBlockingPool: NIOThreadPool = {
110
0
    guard NIOSingletons.singletonsEnabledSuggestion else {
111
0
        fatalError(
112
0
            """
113
0
            Cannot create global singleton NIOThreadPool because the global singletons have been \
114
0
            disabled by setting `NIOSingletons.singletonsEnabledSuggestion = false`
115
0
            """
116
0
        )
117
0
    }
118
0
    let pool = NIOThreadPool._makePerpetualStartedPool(
119
0
        numberOfThreads: NIOSingletons.blockingPoolThreadCountSuggestion,
120
0
        threadNamePrefix: "SGLTN-TP-#"
121
0
    )
122
0
    _ = Unmanaged.passRetained(pool)  // never gonna let you down.
123
0
    return pool
124
0
}()
125
#endif  // !os(WASI)