forked from vapor/postgres-nio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPoolStateMachine+RequestQueue.swift
71 lines (60 loc) · 2.41 KB
/
PoolStateMachine+RequestQueue.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
import DequeModule
@available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
extension PoolStateMachine {
/// A request queue, which can enqueue requests in O(1), dequeue requests in O(1) and even cancel requests in O(1).
///
/// While enqueueing and dequeueing on O(1) is trivial, cancellation is hard, as it normally requires a removal within the
/// underlying Deque. However thanks to having an additional `requests` dictionary, we can remove the cancelled
/// request from the dictionary and keep it inside the queue. Whenever we pop a request from the deque, we validate
/// that it hasn't been cancelled in the meantime by checking if the popped request is still in the `requests` dictionary.
@usableFromInline
struct RequestQueue {
@usableFromInline
private(set) var queue: Deque<RequestID>
@usableFromInline
private(set) var requests: [RequestID: Request]
@inlinable
var count: Int {
self.requests.count
}
@inlinable
var isEmpty: Bool {
self.count == 0
}
@usableFromInline
init() {
self.queue = .init(minimumCapacity: 256)
self.requests = .init(minimumCapacity: 256)
}
@inlinable
mutating func queue(_ request: Request) {
self.requests[request.id] = request
self.queue.append(request.id)
}
@inlinable
mutating func pop(max: UInt16) -> OneElementFastSequence<Request> {
var result = OneElementFastSequence<Request>()
result.reserveCapacity(Int(max))
var popped = 0
while let requestID = self.queue.popFirst(), popped < max {
if let requestIndex = self.requests.index(forKey: requestID) {
popped += 1
result.append(self.requests.remove(at: requestIndex).value)
}
}
assert(result.count <= max)
return result
}
@inlinable
mutating func remove(_ requestID: RequestID) -> Request? {
self.requests.removeValue(forKey: requestID)
}
@inlinable
mutating func removeAll() -> OneElementFastSequence<Request> {
let result = OneElementFastSequence(self.requests.values)
self.requests.removeAll()
self.queue.removeAll()
return result
}
}
}