프로그램 구조

동시성

이름 붙은 작업을 제한 시간 안에서 실행하고 성공·시간 초과·Result·실행 오류를 구분합니다.

서로 독립적인 표현식을 함께 실행하고 그 결과를 이름 붙은 레코드 하나로 받고 싶을 때 concurrent를 사용합니다. 일반 애플리케이션 코드에서는 대체 값을 분명히 적어 둔 제한 시간 형식을 고르세요.

제한 시간 안에 완료하기

다음 코드를 concurrency-success.tpz로 저장합니다.

TOPAZ
let result = concurrent(timeout: 3s) {
    total: 1 + 2
    label: "ready"
} else {
    { total: -1, label: "timeout" }
}

print("{result.total} {result.label}")

검사한 뒤 실행합니다.

BASH
topaz check concurrency-success.tpz
topaz run concurrency-success.tpz

두 작업 모두 제한 시간 안에 끝납니다. 그래서 각 이름이 결과 레코드의 필드가 됩니다.

출력
3 ready

레코드는 작업 이름과 값을 연결합니다. 어느 작업이 먼저 시작하거나 끝났는지는 이 결과에서 알 수 없습니다.

시간 초과 시 대체 값 선택하기

두 번째 프로그램에는 끝나지 않는 작업이 있습니다. 다음 코드를 concurrency-timeout.tpz로 저장합니다.

TOPAZ
function spin() -> int {
    let mut i = 0
    while true { i += 1 }
    i
}

let result = concurrent(timeout: 5ms) {
    stuck: spin()
} else {
    { stuck: -1 }
}

print("{result.stuck}")

검사한 뒤 실행합니다.

BASH
topaz check concurrency-timeout.tpz
topaz run concurrency-timeout.tpz

제한 시간이 먼저 끝나면 일부 작업의 결과는 밖으로 나오지 않습니다. 이때는 else가 전체 결과를 만듭니다.

출력
-1

세 가지 결과 구분하기

제한 시간 전에 일어난 일표현식의 결과
모든 작업이 완료됨작업마다 하나의 필드를 가진 레코드
제한 시간이 먼저 끝남else 블록의 값
한 작업에서 실행 오류가 발생함전체 표현식이 실행 오류로 끝나며 else는 실행되지 않음

작업이 Err(error)를 계산했다면 실행 오류가 아닙니다. 그 Result는 이름 붙은 레코드 필드에 담기는 보통 값입니다. 대체 값은 성공한 작업 레코드와 타입이 호환되어야 합니다. 그래서 두 예제의 성공 경로와 else 경로는 같은 필드 이름을 쓰고 값 타입도 서로 맞춥니다.

이름이 보장하지 않는 것

작업 이름은 결과와의 연결만 고정합니다. 실행 순서까지 고정하지는 않습니다. 토파즈는 작업 시작 순서, 완료 순서, 출력이 섞이는 순서, 공정성, 결정적인 실행 순서를 보장하지 않습니다. 순서가 중요하다면 작업 안에서 print하지 마세요. 예제처럼 합류한 뒤에 레코드를 출력하세요.

시간이 초과된 뒤 남은 작업을 어떻게 취소하고 정리할지는 런타임 정책이 정합니다. 버려진 작업에서 나중에 실행 오류가 나도 토파즈 표현식은 그것을 보지 못합니다. 그러니 특정 스케줄러를 전제로 삼거나 시간 초과 뒤의 정리가 어디서나 같다고 전제하면 안 됩니다.

흔한 수정

  • 3s5ms처럼 숫자와 단위를 붙여 씁니다. .seconds 같은 속성 형식은 시간 리터럴이 아닙니다.
  • 제한 시간을 쓰면 else가 반드시 있어야 합니다. 제한 시간 없이 합류만 할 때는 else를 붙일 수 없습니다.
  • else는 시간 초과만 처리합니다. 실행 오류를 잡거나 Err를 풀지 않습니다.
  • 작업 이름은 중복될 수 없습니다. 결과 일부만 꺼내는 문법도 없습니다.

제한 시간이 없는 concurrent { ... } 합류는 기다림 자체가 설명의 핵심인 고급 동시성 문서에서 쓸 수 있습니다. 일반 예제의 기본 형식은 아닙니다.

암묵적인 비동기 모델, async/await 문법, 공개 작업 핸들, 일반 시간 연산, 명시된 취소 프로토콜은 없습니다. 관찰할 수 있는 실행 오류와 순서의 경계는 실행 환경 동작에서 확인하세요. 익숙해 보이지만 지원하지 않는 형식은 금지·유예 형식에서 확인하세요.