- Published on
Sendable protokoli nima? (@unchecked Sendable)
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Nega bizga Sendable kerak?
Oldingi darslarda biz Actor'lar orqali ma'lumotni Data Race (to'qnashuv) dan himoya qilishni ko'rib chiqdik. Tasavvur qiling, sizda mukammal ishlangan xavfsiz Actor bor. Lekin siz u actor ichidagi qandaydir funksiyaga oddiy Class (Class = Reference type, ya'ni xavfsiz emas) turidagi obyektni parametr sifatida berib yubordingiz.
Actor garchan o'zining ichki ma'lumotlarini himoya qilsa ham, siz uning ichiga berib yuborgan Class obyekti xavfsiz emasdi. O'sha Class obyektini ayni vaqtda boshqa qandaydir Thread (oqim) o'zgartirishi ehtimoli mavjud. Bu degani himoyalangan actor ichiga "xavfli dushman" kirib keldi degani!
Mana shunday xavfli obyektlar asinxron muhitga kirib kelmasligi uchun Swift Sendable protokolini joriy qilgan.
Sendable nima qiladi?
Sendable – bu qandaydir ma'lumot turining (struct, class, enum) bir asinxron joydan ikkinchi asinxron joyga xavfsiz tarzda o'tkazilishi (yuborilishi) mumkinligini ko'rsatuvchi majburiy sertifikatdir.
1. Struct'lar (Value Type)
Oldingi darslardan bilamizki, Struct'lar, String'lar, Integer'lar – bular Value Type hisoblanadi. Ular har safar uzatilganda nusxasi ko'chiriladi. Demak, ular hech qachon xotirada to'qnashmaydi (Thread-safe).
Shu sababli barcha Struct'lar o'z-o'zidan Sendable hisoblanadi.
// Bu Struct doimo xavfsiz, uni istalgan Actor ga berish mumkin
struct MyUserInfo: Sendable {
var name: String
}
2. Class'lar (Reference Type)
Class'lar xotirada nusxa ko'chirmaydi, balki havola (pointer) beradi. Shuning uchun ular asinxron muhitda yuborilishga xavfli hisoblanadi. Agar siz Class ni Sendable qilishga urinsangiz, tizim xato beradi!
Class'ni Sendable (xavfsiz yuboriladigan) qilishning qat'iy qoidalari bor:
- U
final classbo'lishi shart (hech kim undan voris olmasligi uchun). - Uning ichidagi barcha o'zgaruvchilar
let(o'zgarmas) bo'lishi shart!
// Bu to'g'ri va xavfsiz Class
final class MyClassUserInfo: Sendable {
let name: String
init(name: String) {
self.name = name
}
}
Agar yuqoridagi class ichidagi name o'zgaruvchisi var bo'lganida, kompyuter sizga: "Sizda o'zgaruvchi bor, bu Sendable bo'la olmaydi!" degan qizil xatoni ko'rsatardi.
3. @unchecked Sendable (Xavfli yo'l!)
Ba'zan ilovalarda biz haqiqatdan ham ichida o'zgaruvchilari (var) bo'lgan klasslarni Actor'larga yuborishga majbur bo'lib qolamiz. (Masalan eski SDK'lar yoki murakkab arxitekturalar sababli).
Bunday hollarda biz kompyuterga: "Meni tekshirma, men o'zim bu kodni to'qnashuvlardan qo'lda himoya qilib olganman" deb va'da berishimiz mumkin. Buning uchun protokol nomi oldiga @unchecked qo'shiladi:
class UnsafeUserInfo: @unchecked Sendable {
// Endi "var" yozsak ham kompyuter xato bermaydi
var name: String = ""
// OGOHLANTIRISH: Agar siz buni yozsangiz, xavfsizlikni
// DispatchQueue va Lock lar orqali O'ZINGIZ ta'minlashingiz SHART!
}
WARNING
Katta dasturlarda @unchecked Sendable ishlatish umuman tavsiya qilinmaydi! Agar iloji bo'lsa, doimo klassingizni Struct'ga yoki Actor'ning o'ziga aylantirish yo'lini izlang.
Xulosa
- Har safar asinxron (async) operatsiyalarga yoki Actor ichiga qandaydir obyektni yubormoqchi bo'lsangiz, tizim sizdan uning
Sendablebo'lishini talab qiladi. - Bu protokol Swift'ga "Bu ma'lumot boshqa threadlar bilan urishib qolmaydi" degan yashil chiroqni beradi.
- Ma'lumot modelingiz asosan Struct'lardan iborat bo'lsa, sizda Sendable bilan muammo chiqmaydi!