Section 5/161 menit

5. Parameter Modifier `sending`

5. Parameter Modifier sending

sending adalah modifier parameter yang menyatakan: "nilai ini dipindahkan ke isolation domain yang berbeda, pengirim tidak boleh mengakses nilai ini setelah pemanggilan."

Sintaks dan Semantik

swift
// Tanpa sending: non-Sendable tidak bisa dikirim ke async context berbeda
func process(_ value: NonSendableType) async { /* ... */ }

// Dengan sending: kompiler memverifikasi pengiriman aman
func process(_ value: sending NonSendableType) async {
    // Nilai diterima di sini — bisa digunakan bebas
    _ = value
}

// Pemanggil: setelah `process()`, tidak boleh akses value lagi
func caller() async {
    let obj = NonSendableType()
    await process(obj)
    // _ = obj  // ❌ Compiler error: obj sudah "dikirim"
}

sending pada Return Value

swift
// Kembalikan nilai yang berpindah dari isolation domain ke caller
actor DataStore {
    private var cache: Cache = Cache()  // Non-Sendable

    // Caller menerima ownership — DataStore tidak simpan lagi
    func extractCache() -> sending Cache {
        let result = cache
        cache = Cache()  // Ganti dengan instance baru
        return result    // Kirim ownership ke caller
    }
}

func processCachedData() async {
    let store = DataStore()
    let cache = await store.extractCache()
    // cache sekarang di-own oleh context ini — aman digunakan
    _ = cache.contents
}

sending dalam Closure Parameter

swift
// Fungsi yang menerima closure yang akan dijalankan di isolation domain berbeda
func runOnBackground<T: Sendable>(
    _ work: sending @Sendable () async -> T
) async -> T {
    await Task.detached { await work() }.value
}

// Non-Sendable yang di-capture harus "dikirim" bersama closure
class WorkItem {  // Non-Sendable
    var progress: Double = 0
}

func scheduleWork() async {
    let item = WorkItem()
    // item di-capture oleh closure yang di-send ke background
    // Setelah ini, item tidak boleh diakses di scope ini
    await runOnBackground { [item] in
        item.progress = 1.0
        return item.progress
    }
}