Section 7/161 menit

7. Region-Based Isolation & `sending` Parameter

7. Region-Based Isolation & sending Parameter

Region-based isolation adalah fitur Swift 5.9+ yang memungkinkan compiler melacak "kepemilikan" nilai dan memperbolehkan transfer non-Sendable value antar isolation domain, asalkan nilai tersebut tidak diakses lagi dari domain asal setelah transfer.

Konsep Region

swift
// Region: sekumpulan nilai yang "terhubung" satu sama lain
class Node {
    var next: Node?
    var value: Int
    init(_ value: Int) { self.value = value }
}

func buildAndSend() async {
    // node1 dan node2 ada dalam region yang sama (terhubung via .next)
    let node1 = Node(1)
    let node2 = Node(2)
    node1.next = node2
    
    // Transfer seluruh region ke actor — AMAN karena tidak diakses lagi
    await processNode(sending node1)
    
    // ❌ Setelah sending, tidak bisa akses node1 atau node2
    // print(node1.value)  // Compiler error: value used after being sent
}

sending Parameter

swift
// 'sending' = parameter ini mengambil ownership dari value
// Konsumen bisa menyimpan atau transfer ke domain lain
actor DataProcessor {
    private var processedItems: [ProcessedData] = []
    
    // 'sending' memungkinkan passing non-Sendable ke actor
    func process(sending rawData: RawData) async -> ProcessedData {
        let result = transform(rawData)  // rawData sekarang "milik" actor ini
        processedItems.append(result)
        return result
    }
}

// RawData tidak perlu Sendable untuk di-pass sebagai 'sending'
class RawData {
    var content: [UInt8]
    init(_ content: [UInt8]) { self.content = content }
}

// Penggunaan
func handleRequest() async {
    let raw = RawData([1, 2, 3, 4])
    
    // Transfer ownership ke actor
    let processor = DataProcessor()
    let result = await processor.process(sending raw)
    
    // raw tidak bisa digunakan lagi di sini setelah 'sending'
    print(result)
}

Merge-Isolated Values

swift
// Dua region bisa di-merge menjadi satu region besar
actor Pipeline {
    func stage1(sending input: InputData) -> IntermediateData {
        IntermediateData(from: input)
    }
    
    func stage2(sending intermediate: IntermediateData) -> OutputData {
        OutputData(from: intermediate)
    }
}

// Chaining: masing-masing stage transfer ownership ke berikutnya
func runPipeline(input: InputData) async -> OutputData {
    let pipeline = Pipeline()
    let intermediate = await pipeline.stage1(sending input)
    return await pipeline.stage2(sending intermediate)
}