@Sendable에서 시작해서 actor까지 이번 포스팅까지 5개의 포스팅을 썼는데요. 일단 이 주제에 대해서는 잠정적으로 마지막 포스팅이 될 것 같습니다.
이번 포스팅에서는 전역함수에서 actor를 parameter로 받을 수 있는 isolated parameter에 대해서 다룹니다.
원칙적으로 actor의 mutatable state를 변경하고 싶을 때는 actor의 인스턴스를 통해서만 접근할 수 있습니다. actor 내부에서 실행해야 isolated context에서 상태를 변경할 수 있기 때문입니다.
actor SomeActor {
var num = 0
func addOne() {
self.num += 1
}
}
await actor.addOne()
전역함수에서 같은 작업을 수행하고자 하면 아래와 같은 에러가 발생하게 되는데요. actor-isolated 속성인 num은 non-isolated 환경에서는 변경할 수 없다고 합니다.
//🚫 Actor-isolated property 'num' can not be mutated from a non-isolated context
func addOneToActor(to actor: SomeActor) {
actor.num += 1
}
parameter의 Actor 타입 앞에 isolated를 붙이면 함수 자체를 actor-isolated context로 만들 수 있습니다.
//✅ 에러 없음
func addOneToActor(to actor: isolated SomeActor) {
actor.num += 1
}
다만 위처럼 하면 위 함수가 actor-isolated context에서 실행되기 때문에 async가 명시 되어 있지 않아도 await를 붙여서 실행해야 합니다.
await addOneToActor(to: actor)
아래와 같은 함수를 구현해봅시다. 아래 함수는 2개의 actor를 parameter로 받아서 두 actor의 num을 모두 바꾸는 함수입니다. 아래 코드가 실행은 되는데 아래와 같은 warning이 뜨는데요… 원인은 아직 잘 모르겠네요… 추측을 해보자면 actor1과 actor2의 actor-isolated context가 서로 다르기 때문이 아닐까 추측을 해봅니다.
actor SomeActor {
var num = 0
func addOne() {
self.num += 1
}
}
func switchNum(actor1: isolated SomeActor, actor2: isolated SomeActor) {
let temp = actor1.num
actor1.num = actor2.num
actor2.num = temp
}
let actor1 = SomeActor()
await actor1.addOne()
let actor2 = SomeActor()
await print(actor1.num, actor2.num)
await switchNum(actor1: actor1, actor2: actor2)
await print(actor1.num, actor2.num)
아직 actor를 실무에서 많이 써본 것이 아니라서 이론에 치중된 포스팅이 된 것 같아서 아쉽습니다. 다음에 기회가 되면 좀 더 디테일하고 실무에 도움이 되는 포스팅으로 Sendable과 Actor를 다루어보겠습니다!