1+ // RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-concurrency %import-libdispatch)
2+
3+ // REQUIRES: executable_test
4+ // REQUIRES: concurrency
5+ // REQUIRES: libdispatch
6+
7+ actor Page {
8+ let initialNumWords : Int
9+
10+ @actorIndependent ( unsafe)
11+ var numWords : Int
12+
13+ init ( _ words : Int ) {
14+ numWords = words
15+ initialNumWords = words
16+ }
17+ }
18+
19+ actor Book {
20+ let pages : [ Page ]
21+
22+ init ( _ numPages : Int ) {
23+ var stack : [ Page ] = [ ]
24+ for i in 0 ..< numPages {
25+ stack. append ( Page ( i) )
26+ }
27+ pages = stack
28+ }
29+
30+ @actorIndependent
31+ subscript( _ page : Int ) -> Page {
32+ return pages [ page]
33+ }
34+ }
35+
36+ func bookHasChanged( _ b : Book ,
37+ currentGetter : KeyPath < Page , Int > ,
38+ initialGetter : ( Page ) -> Int ) -> Bool {
39+ let numPages = b [ keyPath: \. pages. count]
40+
41+ for i in 0 ..< numPages {
42+ let pageGetter = \Book . [ i]
43+ let currentWords = pageGetter. appending ( path: currentGetter)
44+
45+ if ( b [ keyPath: currentWords] != initialGetter ( b [ keyPath: pageGetter] ) ) {
46+ return true
47+ }
48+ }
49+
50+ return false
51+ }
52+
53+ func enumeratePageKeys( from : Int , to : Int ) -> [ KeyPath < Book , Page > ] {
54+ var keys : [ KeyPath < Book , Page > ] = [ ]
55+ for i in from ..< to {
56+ keys. append ( \Book . [ i] )
57+ }
58+ return keys
59+ }
60+
61+ func erasePages( _ book : Book , badPages: [ KeyPath < Book , Page > ] ) {
62+ for page in badPages {
63+ book [ keyPath: page] . numWords = 0
64+ }
65+ }
66+
67+ let book = Book ( 100 )
68+
69+ if bookHasChanged ( book, currentGetter: \Page . numWords, initialGetter: \Page . initialNumWords) {
70+ fatalError ( " book should not be changed " )
71+ }
72+
73+ erasePages ( book, badPages: enumeratePageKeys ( from: 0 , to: 100 ) )
74+
75+ guard bookHasChanged ( book, currentGetter: \Page . numWords, initialGetter: \Page . initialNumWords) else {
76+ fatalError ( " book should be wiped! " )
77+ }
0 commit comments