Skip to content

Commit e947421

Browse files
authored
Allow in-place mutation of NIOLoopBoundBox.value (#2771)
* Allow in-place mutation of `NIOLoopBoundBox.value` * Fix typos in docs
1 parent 9b86559 commit e947421

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

Sources/NIOCore/NIOLoopBound.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ public struct NIOLoopBound<Value>: @unchecked Sendable {
4747
self._eventLoop.preconditionInEventLoop()
4848
return self._value
4949
}
50-
set {
50+
_modify {
5151
self._eventLoop.preconditionInEventLoop()
52-
self._value = newValue
52+
yield &self._value
5353
}
5454
}
5555
}
@@ -136,9 +136,9 @@ public final class NIOLoopBoundBox<Value>: @unchecked Sendable {
136136
self._eventLoop.preconditionInEventLoop()
137137
return self._value
138138
}
139-
set {
139+
_modify {
140140
self._eventLoop.preconditionInEventLoop()
141-
self._value = newValue
141+
yield &self._value
142142
}
143143
}
144144
}

Tests/NIOPosixTests/CoWValue.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftNIO open source project
4+
//
5+
// Copyright (c) 2024 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+
/// A Copy on Write (CoW) type that can be used in tests to assert in-place mutation
16+
struct CoWValue: @unchecked Sendable {
17+
private final class UniquenessIndicator {}
18+
19+
/// This reference is "copied" if not uniquely referenced
20+
private var uniquenessIndicator = UniquenessIndicator()
21+
22+
/// mutates `self` and returns a boolean whether it was mutated in place or not
23+
/// - Returns: true if mutation happened in-place, false if Copy on Write (CoW) was triggered
24+
mutating func mutateInPlace() -> Bool {
25+
guard isKnownUniquelyReferenced(&self.uniquenessIndicator) else {
26+
self.uniquenessIndicator = UniquenessIndicator()
27+
return false
28+
}
29+
return true
30+
}
31+
}

Tests/NIOPosixTests/NIOLoopBoundTests.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ final class NIOLoopBoundTests: XCTestCase {
6868
}.wait())
6969
}
7070

71+
func testInPlaceMutation() {
72+
var loopBound = NIOLoopBound(CoWValue(), eventLoop: loop)
73+
XCTAssertTrue(loopBound.value.mutateInPlace())
74+
75+
let loopBoundBox = NIOLoopBoundBox(CoWValue(), eventLoop: loop)
76+
XCTAssertTrue(loopBoundBox.value.mutateInPlace())
77+
}
78+
7179
// MARK: - Helpers
7280
func sendableBlackhole<S: Sendable>(_ sendableThing: S) {}
7381

0 commit comments

Comments
 (0)