<@Sendable은 무엇인가?> 6. isolated parameter

SteadySlower·2023년 7월 21일
0

iOS Development

목록 보기
28/38

@Sendable에서 시작해서 actor까지 이번 포스팅까지 5개의 포스팅을 썼는데요. 일단 이 주제에 대해서는 잠정적으로 마지막 포스팅이 될 것 같습니다.

이번 포스팅에서는 전역함수에서 actor를 parameter로 받을 수 있는 isolated parameter에 대해서 다룹니다.

전역함수에서 actor를 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
}

isolated parameter: 전역함수를 actor-isolated context 하게 만들기

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-isolated context?

아래와 같은 함수를 구현해봅시다. 아래 함수는 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를 다루어보겠습니다!

profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글