Section 8/171 menit

8. @Sendable Closure dan sending Parameters

8. @Sendable Closure dan sending Parameters

@Sendable Closure: Aturan Capture

Closure @Sendable tidak boleh capture state yang non-Sendable atau mutable:

swift
var counter = 0  // var → non-Sendable capture

Task {
    counter += 1  // ❌ Error: capture of 'counter' with non-sendable type
}

// ✓ Capture immutable:
let snapshot = counter
Task { print(snapshot) }

Closure yang ditandai @Sendable (atau yang diinference sebagai Sendable, seperti closure di Task.init) tidak boleh:

  • Capture var lokal.
  • Capture instance non-Sendable (misal class non-Sendable).
  • Memanggil inout parameter di luar lifetime-nya.

sending Keyword (Swift 6)

sending adalah transfer semantics: parameter yang ditandai sending artinya "saya menyerahkan kepemilikan value ini, kamu boleh memindahkannya ke isolation domain lain".

swift
// Sebelum sending — value harus Sendable
func process(_ data: SomeSendableType) async { }

// Dengan sending — value boleh non-Sendable, tapi caller harus
// melepaskan akses setelah dikirim
func process(_ data: sending SomeType) async { }

Ini berguna untuk objek yang sebenarnya aman ditransfer sekali (misal: builder yang baru dibuat lalu diteruskan ke actor) tapi bukan Sendable secara general.

swift
final class ImageBuffer {
    var pixels: [UInt8] = []
    // tidak Sendable: var properties
}

actor ImageProcessor {
    func process(_ buffer: sending ImageBuffer) async {
        // Setelah dipanggil, caller tidak boleh akses buffer lagi
        // (compiler akan menolak akses post-call di caller)
    }
}

// Caller:
let buf = ImageBuffer()
buf.pixels = generatePixels()
await processor.process(buf)
// buf.pixels.append(...)  // ❌ Error: 'buf' was transferred

Compiler melacak ini lewat region analysis (Bagian 9).

sending vs inout vs Borrowing

Modifier Semantik Kepemilikan setelah call
(default) Copy / shared borrow Caller masih punya
inout Mutable borrow Caller masih punya, mungkin dimutasi
borrowing Read-only borrow Caller masih punya
consuming Move Caller tidak punya lagi
sending Transfer antar domain Caller tidak boleh pakai lagi

sending dan consuming mirip semantik, tapi sending khusus untuk isolation transfer.