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:
- Value type (
struct,enum): Sendable kalau semua stored property-nya Sendable. - Class final: Sendable kalau semua stored property
letdan Sendable, dan tidak ada superclass non-Sendable. - Actor: otomatis Sendable (state di-protect oleh actor).
- Function/closure: ditandai
@Sendable.
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:
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:
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:
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.