Section 7/172 menit

7. Sendable: Static Checking Cross-Domain Transfer

7. Sendable: Static Checking Cross-Domain Transfer

Sendable adalah marker protocol — tidak punya requirement. Tujuannya: memberi tahu compiler bahwa value bisa diteruskan antar isolation domain dengan aman.

Cara Kerja Conformance Checking

Compiler memeriksa Sendable secara structural:

  1. Value type (struct, enum): Sendable kalau semua stored property-nya Sendable.
  2. Class final: Sendable kalau semua stored property let dan Sendable, dan tidak ada superclass non-Sendable.
  3. Actor: otomatis Sendable (state di-protect oleh actor).
  4. Function/closure: ditandai @Sendable.
swift
struct Coordinate: Sendable {
    let x: Double  // ✓ Sendable
    let y: Double  // ✓ Sendable
}

struct Container: Sendable {  // ❌ Error
    let item: NSMutableArray  // NSMutableArray bukan Sendable
}

@unchecked Sendable: Janji ke Compiler

Saat kamu yakin sebuah tipe thread-safe tapi compiler tidak bisa buktikan, gunakan @unchecked Sendable:

swift
final class ConfigStore: @unchecked Sendable {
    private let lock = NSLock()
    private var _value: Config

    init(initial: Config) { _value = initial }

    var value: Config {
        lock.withLock { _value }
    }

    func update(_ new: Config) {
        lock.withLock { _value = new }
    }
}

Aturan main: kamu bertanggung jawab atas thread safety — compiler tidak akan menolong. Pakai hanya untuk:

  • Wrapper sekitar lock/atomic manual.
  • Immutable class (semua field let, tapi class non-final).
  • Bridging dengan Objective-C class yang dokumentasinya menjamin thread-safe.

Conditional Sendable

Generic tipe bisa konform Sendable secara kondisional:

swift
struct Box<Value> {
    let value: Value
}

extension Box: Sendable where Value: Sendable { }

let intBox = Box(value: 42)  // Sendable
let arrayBox = Box(value: [1, 2, 3])  // Sendable
let mutBox = Box(value: NSMutableArray())  // bukan Sendable

Pattern ini ada di hampir semua tipe standar library (Array, Dictionary, Optional, Result).

Sendable dan Class Hierarchy

Class non-final yang Sendable harus memastikan subclass-nya juga aman:

swift
class Base: Sendable {
    let id: Int = 0
}

// ❌ Error: stored property mutable di subclass dari Sendable class
class Sub: Base {
    var counter = 0
}

Solusi: declare base sebagai @unchecked Sendable atau buat subclass tetap mengikuti aturan.

Mengapa Sendable Bukan Runtime Check

Sendable murni compile-time. Tidak ada cost runtime. Ini berbeda dari pattern di banyak bahasa lain yang melakukan transfer check saat data dipindah.

Konsekuensi: kalau kamu salah @unchecked Sendable, tidak ada error runtime — hanya data race senyap. Tes & review @unchecked dengan ekstra hati-hati.