-
Notifications
You must be signed in to change notification settings - Fork 15
/
NonBlockingSpinningState.swift
76 lines (64 loc) · 2.67 KB
/
NonBlockingSpinningState.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Copyright 2020 Penguin Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: once some version of atomics lands in Swift, refactor this to make it much nicer!
/// A helper that packs the spinning state of the `NonBlockingThreadPool` into 64 bits.
internal struct NonBlockingSpinningState {
var underlying: UInt64
init(_ underlying: UInt64) { self.underlying = underlying }
/// The number of spinning worker threads.
var spinningCount: UInt64 {
get {
underlying & Self.spinningCountMask
}
set {
assert(newValue < Self.spinningCountMask, "new value: \(newValue)")
underlying = (underlying & ~Self.spinningCountMask) | newValue
}
}
/// Number of non-notifying submissions into the pool.
var noNotifyCount: UInt64 {
(underlying & Self.noNotifyCountMask) >> Self.noNotifyCountShift
}
/// True iff a task has been submitted to the pool without notifying the thread pool's `condition`.
var hasNoNotifyTask: Bool {
(underlying & Self.noNotifyCountMask) != 0
}
/// Returns a new state with the the non-notifying count incremented by one.
func incrementingNoNotifyCount() -> Self {
Self(underlying + Self.noNotifyCountIncrement)
}
/// Decrements the non-notifying count by one.
mutating func decrementNoNotifyCount() {
underlying -= Self.noNotifyCountIncrement
}
/// Returns a new state with the spinning count incremented by one.
func incrementingSpinningCount() -> Self {
Self(underlying + 1)
}
/// Returns a new state with the spinning count decremented by one.
func decrementingSpinningCount() -> Self {
Self(underlying - 1)
}
static let spinningCountBits: UInt64 = 32
static let spinningCountMask: UInt64 = (1 << spinningCountBits) - 1
static let noNotifyCountBits: UInt64 = 32
static let noNotifyCountShift: UInt64 = 32
static let noNotifyCountMask: UInt64 = ((1 << noNotifyCountBits) - 1) << noNotifyCountShift
static let noNotifyCountIncrement: UInt64 = (1 << noNotifyCountShift)
}
extension NonBlockingSpinningState: CustomStringConvertible {
public var description: String {
"NonblockingSpinningState(spinningCount: \(spinningCount), noNotifyCount: \(noNotifyCount))"
}
}