Skip to content

Commit 9d2ad25

Browse files
committed
---
yaml --- r: 343038 b: refs/heads/master-rebranch c: d5ea371 h: refs/heads/master
1 parent 7583cf6 commit 9d2ad25

File tree

3 files changed

+195
-1
lines changed

3 files changed

+195
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,7 @@ refs/tags/swift-DEVELOPMENT-SNAPSHOT-2019-08-02-a: ddd2b2976aa9bfde5f20fe37f6bd2
14551455
refs/tags/swift-DEVELOPMENT-SNAPSHOT-2019-08-03-a: 171cc166f2abeb5ca2a4003700a8a78a108bd300
14561456
refs/heads/benlangmuir-patch-1: baaebaf39d52f3bf36710d4fe40cf212e996b212
14571457
refs/heads/i-do-redeclare: 8c4e6d5de5c1e3f0a2cedccf319df713ea22c48e
1458-
refs/heads/master-rebranch: b8dc0f473567fa8751aabad4b778f1aa19a59676
1458+
refs/heads/master-rebranch: d5ea371eed31ede3e38fb1a8cb1b74999c059f24
14591459
refs/heads/rdar-53901732: 9bd06af3284e18a109cdbf9aa59d833b24eeca7b
14601460
refs/heads/revert-26776-subst-always-returns-a-type: 1b8e18fdd391903a348970a4c848995d4cdd789c
14611461
refs/heads/tensorflow-merge: 8b854f62f80d4476cb383d43c4aac2001dde3cec

branches/master-rebranch/stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ public func expectFailure(
154154
_anyExpectFailed.orAndFetch(startAnyExpectFailed)
155155
}
156156

157+
/// An opaque function that ignores its argument and returns nothing.
158+
public func noop<T>(_ value: T) {}
159+
160+
/// An opaque function that simply returns its argument.
161+
public func identity<T>(_ value: T) -> T {
162+
return value
163+
}
164+
157165
public func identity(_ element: OpaqueValue<Int>) -> OpaqueValue<Int> {
158166
return element
159167
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: executable_test
3+
// REQUIRES: objc_interop
4+
5+
import StdlibUnittest
6+
import ObjectiveC // for autoreleasepool
7+
8+
var suite = TestSuite("AutoreleasingUnsafeMutablePointer")
9+
10+
/// Call `body` passing it an AutoreleasingUnsafeMutablePointer whose pointee
11+
/// has the specified value, allocated in a temporary buffer.
12+
func withAUMP<Pointee: AnyObject>(
13+
as type: Pointee.Type = Pointee.self,
14+
initialValue: Optional<Unmanaged<Pointee>> = nil,
15+
_ body: (AutoreleasingUnsafeMutablePointer<Optional<Pointee>>) -> Void
16+
) {
17+
let p =
18+
UnsafeMutablePointer<Optional<Unmanaged<Pointee>>>.allocate(capacity: 1)
19+
p.initialize(to: initialValue)
20+
body(AutoreleasingUnsafeMutablePointer(p))
21+
p.deallocate()
22+
}
23+
24+
/// Call `body` passing it an AutoreleasingUnsafeMutablePointer whose pointee
25+
/// has the specified value, allocated in a temporary buffer.
26+
func withAUMP<Pointee: AnyObject>(
27+
initialValues: [Unmanaged<Pointee>?],
28+
_ body: (AutoreleasingUnsafeMutablePointer<Optional<Pointee>>) -> Void
29+
) {
30+
let p = UnsafeMutablePointer<Optional<Unmanaged<Pointee>>>.allocate(
31+
capacity: initialValues.count
32+
)
33+
for i in 0 ..< initialValues.count {
34+
(p + i).initialize(to: initialValues[i])
35+
}
36+
37+
let aump = AutoreleasingUnsafeMutablePointer<Optional<Pointee>>(p)
38+
body(aump)
39+
p.deallocate()
40+
}
41+
42+
suite.test("helper calls its closure exactly once") {
43+
// `withAUMP` is expected to call its closure exactly once, with an argument
44+
// pointing to a nil value.
45+
var runCount = 0
46+
withAUMP(as: LifetimeTracked.self) { p in
47+
runCount += 1
48+
expectNil(p.pointee)
49+
}
50+
expectEqual(runCount, 1)
51+
}
52+
53+
suite.test("init doesn't autorelease") {
54+
let originalInstances = LifetimeTracked.instances
55+
let unmanaged = Unmanaged.passRetained(LifetimeTracked(42))
56+
expectEqual(LifetimeTracked.instances, originalInstances + 1)
57+
58+
withAUMP(initialValue: unmanaged) { p in noop(p) }
59+
60+
// Releasing the original reference should immediately deallocate the
61+
// object.
62+
expectEqual(LifetimeTracked.instances, originalInstances + 1)
63+
unmanaged.release()
64+
expectEqual(LifetimeTracked.instances, originalInstances)
65+
}
66+
67+
suite.test("getter initially returns the initial value") {
68+
withAUMP(as: LifetimeTracked.self) { p in
69+
expectNil(p.pointee)
70+
}
71+
72+
let unmanaged = Unmanaged.passRetained(LifetimeTracked(42))
73+
withAUMP(initialValue: unmanaged) { p in
74+
expectTrue(p.pointee === unmanaged.takeUnretainedValue())
75+
}
76+
unmanaged.release()
77+
}
78+
79+
suite.test("pointee getter returns the last value set") {
80+
autoreleasepool {
81+
withAUMP(as: LifetimeTracked.self) { p in
82+
expectNil(p.pointee)
83+
let object = LifetimeTracked(23)
84+
p.pointee = object
85+
expectTrue(p.pointee === object)
86+
let other = LifetimeTracked(42)
87+
p.pointee = other
88+
expectTrue(p.pointee === other)
89+
p.pointee = nil
90+
expectNil(p.pointee)
91+
}
92+
}
93+
}
94+
95+
suite.test("pointee getter doesn't autorelease") {
96+
let originalInstances = LifetimeTracked.instances
97+
autoreleasepool {
98+
let unmanaged = Unmanaged.passRetained(LifetimeTracked(42))
99+
expectEqual(LifetimeTracked.instances, originalInstances + 1)
100+
101+
withAUMP(initialValue: unmanaged) { p in
102+
expectTrue(p.pointee === unmanaged.takeUnretainedValue())
103+
}
104+
// Releasing the original reference should immediately deallocate the
105+
// object.
106+
expectEqual(LifetimeTracked.instances, originalInstances + 1)
107+
unmanaged.release()
108+
expectEqual(LifetimeTracked.instances, originalInstances)
109+
}
110+
}
111+
112+
suite.test("pointee setter autoreleases the new value") {
113+
let originalInstances = LifetimeTracked.instances
114+
autoreleasepool {
115+
withAUMP(as: LifetimeTracked.self) { p in
116+
let object = LifetimeTracked(42)
117+
// There is one more instance now.
118+
expectEqual(LifetimeTracked.instances, originalInstances + 1)
119+
p.pointee = object
120+
}
121+
// The strong reference to `object` is gone, but the autoreleasepool
122+
// is still holding onto it.
123+
expectEqual(LifetimeTracked.instances, originalInstances + 1)
124+
}
125+
// Draining the pool deallocates the instance.
126+
expectEqual(LifetimeTracked.instances, originalInstances)
127+
}
128+
129+
suite.test("AutoreleasingUnsafeMutablePointer doesn't retain its value") {
130+
let originalInstances = LifetimeTracked.instances
131+
withAUMP(as: LifetimeTracked.self) { p in
132+
autoreleasepool {
133+
let object = LifetimeTracked(42)
134+
p.pointee = object
135+
expectEqual(LifetimeTracked.instances, originalInstances + 1)
136+
}
137+
// Draining the pool deallocates the instance, even though
138+
// the autoreleasing pointer still points to it.
139+
// This is okay as long as the pointer isn't dereferenced.
140+
expectEqual(LifetimeTracked.instances, originalInstances)
141+
}
142+
expectEqual(LifetimeTracked.instances, originalInstances)
143+
}
144+
145+
suite.test("subscript[0] is the same as pointee.getter") {
146+
withAUMP(as: LifetimeTracked.self) { p in
147+
expectNil(p[0])
148+
}
149+
150+
let unmanaged = Unmanaged.passRetained(LifetimeTracked(42))
151+
withAUMP(initialValue: unmanaged) { p in
152+
expectTrue(p[0] === unmanaged.takeUnretainedValue())
153+
}
154+
unmanaged.release()
155+
}
156+
157+
158+
suite.test("subscript and advanced(by:) works") {
159+
let originalInstances = LifetimeTracked.instances
160+
let count = 100
161+
162+
var refs = 0
163+
let values: [Unmanaged<LifetimeTracked>?] = (0 ..< count).map { i in
164+
if i % 10 == 0 {
165+
refs += 1
166+
return Unmanaged.passRetained(LifetimeTracked(i))
167+
} else {
168+
return nil
169+
}
170+
}
171+
172+
withAUMP(initialValues: values) { p in
173+
for i in 0 ..< count {
174+
expectTrue(p[i] === values[i]?.takeUnretainedValue())
175+
expectTrue(p.advanced(by: i).pointee === values[i]?.takeUnretainedValue())
176+
}
177+
}
178+
179+
expectEqual(LifetimeTracked.instances, originalInstances + refs)
180+
for unmanaged in values {
181+
unmanaged?.release()
182+
}
183+
expectEqual(LifetimeTracked.instances, originalInstances)
184+
}
185+
186+
runAllTests()

0 commit comments

Comments
 (0)