@@ -21,6 +21,64 @@ class D {
2121 }
2222}
2323
24+ class DataWrapper {
25+
26+ var pointer : UnsafeMutableRawBufferPointer
27+
28+ init ( count: Int ) {
29+ pointer = UnsafeMutableRawBufferPointer . allocate ( byteCount: count, alignment: MemoryLayout< Int> . alignment)
30+ }
31+
32+ var bytes : UnsafeMutableRawBufferPointer { return pointer }
33+
34+ deinit {
35+ pointer. deallocate ( )
36+ }
37+ }
38+
39+ var fileHandleMap : [ Int32 : String ] = [ : ]
40+
41+ func openTheFile( _ path: String ) -> Int32 {
42+ let fd : Int32 = 42
43+ assert ( fileHandleMap [ fd] == nil )
44+ fileHandleMap [ fd] = path
45+ return fd
46+ }
47+
48+ func closeTheFile( _ fd: Int32 ) {
49+ fileHandleMap. removeValue ( forKey: fd)
50+ }
51+
52+ func writeToTheFile( _ fd: Int32 ) {
53+ assert ( fileHandleMap [ fd] != nil )
54+ }
55+
56+ class FileHandleWrapper {
57+
58+ var handle : Int32 ? = nil
59+
60+ func open( path: String ) {
61+ let fd = openTheFile ( path)
62+ if fd >= 0 {
63+ handle = fd
64+ }
65+ }
66+
67+ func close( ) {
68+ if let fd = handle {
69+ closeTheFile ( fd)
70+ handle = nil
71+ }
72+ }
73+
74+ deinit {
75+ if let fd = handle {
76+ closeTheFile ( fd)
77+ }
78+ }
79+ }
80+
81+
2482// =============================================================================
2583// = Declarations }} =
2684// =============================================================================
@@ -29,27 +87,71 @@ class D {
2987// = Tests {{ =
3088// =============================================================================
3189
32- func test_localLetKeepsObjectAliveBeyondCallToClassWithWeakReference ( ) {
90+ func test_localLet_keepsObjectAliveBeyondCallToClassWithWeakReference ( ) {
3391 let d = D ( )
3492 let c = C ( d)
35- // CHECK: cWillFoo{{.*}} test_localLetKeepsObjectAliveBeyondCallToClassWithWeakReference
93+ // CHECK: cWillFoo{{.*}} test_localLet_keepsObjectAliveBeyondCallToClassWithWeakReference
3694 c. foo ( #function)
3795}
3896
39- func test_localVarKeepsObjectAliveBeyondCallToClassWithWeakReference ( ) {
97+ func test_localVar_keepsObjectAliveBeyondCallToClassWithWeakReference ( ) {
4098 var d = D ( )
4199 let c = C ( d)
42- // CHECK: cWillFoo{{.*}} test_localVarKeepsObjectAliveBeyondCallToClassWithWeakReference
100+ // CHECK: cWillFoo{{.*}} test_localVar_keepsObjectAliveBeyondCallToClassWithWeakReference
43101 c. foo ( #function)
44102}
45103
104+ func test_localLet_keepsObjectAliveBeyondCallToClassWithPointer_doit( _ input: [ UInt8 ] ) {
105+ let data = DataWrapper ( count: input. count)
106+ data. bytes. copyBytes ( from: input)
107+ }
108+ func test_localLet_keepsObjectAliveBeyondCallToClassWithPointer( ) {
109+ test_localLet_keepsObjectAliveBeyondCallToClassWithPointer_doit ( [ 1 , 2 , 3 , 4 , 50 ] )
110+ }
111+
112+ func test_localVar_keepsObjectAliveBeyondCallToClassWithPointer_doit( _ input: [ UInt8 ] ) {
113+ let data = DataWrapper ( count: input. count)
114+ data. bytes. copyBytes ( from: input)
115+ }
116+ func test_localVar_keepsObjectAliveBeyondCallToClassWithPointer( ) {
117+ test_localVar_keepsObjectAliveBeyondCallToClassWithPointer_doit ( [ 1 , 2 , 3 , 4 , 50 ] )
118+ }
119+
120+ func test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction_doit( _ path: String ) {
121+ var file = FileHandleWrapper ( )
122+ file. open ( path: path)
123+ // Retrieving 'fd' is the last use of 'file'
124+ guard let fd = file. handle else { return }
125+ // 'fd' has now been closed. The subsequent write will fail.
126+ writeToTheFile ( fd)
127+ }
128+ func test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction( ) {
129+ test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction_doit ( " blue " )
130+ }
131+
132+ func test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction_doit( _ path: String ) {
133+ var file = FileHandleWrapper ( )
134+ file. open ( path: path)
135+ // Retrieving 'fd' is the last use of 'file'
136+ guard let fd = file. handle else { return }
137+ // 'fd' has now been closed. The subsequent write will fail.
138+ writeToTheFile ( fd)
139+ }
140+ func test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction( ) {
141+ test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction_doit ( " blue " )
142+ }
143+
46144// =============================================================================
47145// = Tests }} =
48146// =============================================================================
49147
50148func run( ) {
51- test_localLetKeepsObjectAliveBeyondCallToClassWithWeakReference ( )
52- test_localVarKeepsObjectAliveBeyondCallToClassWithWeakReference ( )
149+ test_localLet_keepsObjectAliveBeyondCallToClassWithWeakReference ( )
150+ test_localVar_keepsObjectAliveBeyondCallToClassWithWeakReference ( )
151+ test_localLet_keepsObjectAliveBeyondCallToClassWithPointer ( )
152+ test_localVar_keepsObjectAliveBeyondCallToClassWithPointer ( )
153+ test_localLet_keepsObjectAliveBeyondCallToSynchronizationPointFunction ( )
154+ test_localVar_keepsObjectAliveBeyondCallToSynchronizationPointFunction ( )
53155}
54156
55157run ( )
0 commit comments