Created
December 14, 2020 16:44
-
-
Save Diggory/da2e82f07efae056f9fe3b9630101c11 to your computer and use it in GitHub Desktop.
Actors in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// https://github.com/DougGregor/swift-evolution/blob/actors/proposals/nnnn-actors.md | |
// Swift Concurrency experiments | |
import Foundation | |
// A simple Actor which has both mutable and immutable value-type stored properties | |
actor class AnActor { | |
let immutable = "I will never chage" | |
var mutable = "I can change" | |
var timesChanged = 0 | |
// Synchronous therefore Actor-Isolated (cannot be called from without the instance.) | |
func test() { | |
print("Hello from the Actor.") | |
print("Changing mutable property") | |
changeMutable() | |
} | |
// Async so can be called from without the instance, but therefore must be awaited upon when called. | |
func testAsync() async { | |
test() | |
} | |
func changeMutable(_ newVal : String = "I have changed") { | |
timesChanged = timesChanged + 1 | |
mutable = newVal + " \(timesChanged) times" | |
} | |
} | |
// An actor singleton to act as the Global Actor | |
actor class TheGlobalActor { | |
static let shared = TheGlobalActor() | |
private init() { } | |
func test() { | |
print("I am the global actor, I don't do much above the surface...") | |
} | |
} | |
@globalActor | |
struct MainContainer { | |
static let shared = TheGlobalActor.shared | |
let simpleActor = AnActor() | |
func main() async { | |
print("Hello main") | |
print("simpleActor.immutable \(simpleActor.immutable) : simpleActor.mutable \(simpleActor.mutable)") | |
// Should fail, but doesn't? test() isn't marked as async. Maybe auto-async magic? | |
await simpleActor.test(); | |
print("simpleActor.immutable \(simpleActor.immutable) : simpleActor.mutable \(simpleActor.mutable)") | |
// Should be OK, as this method is a convenience async one. | |
await simpleActor.testAsync() | |
print("simpleActor.immutable \(simpleActor.immutable) : simpleActor.mutable \(simpleActor.mutable)") | |
} | |
} | |
// Non-globalActor access to an actor? | |
let badActor = AnActor() | |
// Should be possible as it's immutable | |
print("badActor.immutable: \(badActor.immutable)") | |
// Should not be possible as it's mutable | |
print("badActor.mutable: \(badActor.mutable)") | |
// GlobalActor access to the actor | |
@MainContainer | |
let mainContainer = MainContainer() | |
// This allows us to call async from a synchronous-only place | |
_ = Task.runDetached(operation: mainContainer.main) | |
let runLoop = RunLoop.current | |
let distantFuture = Date.distantFuture | |
/// Set this to false when we want to exit the app... | |
var shouldKeepRunning = true | |
while shouldKeepRunning == true && | |
runLoop.run(mode:.default, before: distantFuture) {} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment