Sendable एक Swift प्रोटोकॉल है जो थ्रेड्स के बीच स्थानांतरण के लिए सुरक्षित प्रकारों को चिह्नित करता है। कंकरेंसी (actor, async/await, Task) के साथ काम करते समय, Swift कंपाइलर आवश्यकता करता है कि पृथक संदर्भों के बीच स्थानांतरित सभी डेटा Sendable के अनुरूप हो। यह असुरक्षित प्रकारों के आकस्मिक स्थानांतरण को रोकता है जो डेटा रेस का कारण बन सकते हैं। प्रोटोकॉल एक अनुबंध के रूप में कार्य करता है: Sendable के अनुरूप प्रकार आंतरिक असंयोजित स्थिति की अनुपस्थिति की गारंटी देता है। WWDC 2021 के अनुसार, सुरक्षित मल्टीथ्रेडेड आर्किटेक्चर डिज़ाइन करते समय Sendable प्रोटोकॉल एक अनिवार्य तत्व है।
मुख्य बिंदु
Sendable Swift मानक पुस्तकालय (SE-0302) का एक प्रोटोकॉल है जो अलगाव डोमेन के बीच स्थानांतरण के लिए सुरक्षित प्रकारों को चिह्नित करता है। अलगाव डोमेन का अर्थ है actor, Task कार्य या @MainActor संदर्भ। Sendable में कोई आवश्यकताएँ नहीं हैं — यह एक सुरक्षा मार्कर के रूप में कार्य करता है।
Swift 5.5 से पहले, डेवलपर DispatchQueue के माध्यम से किसी भी ऑब्जेक्ट को थ्रेड्स के बीच स्थानांतरित कर सकते थे, और कंपाइलर जाँच नहीं करता था कि यह सुरक्षित है या नहीं। Sendable इस अंतर को बंद करता है: अब कंपाइलर स्वयं क्रॉस-थ्रेड स्थानांतरण को ट्रैक करता है और असुरक्षित स्थानांतरण को रोकता है। यह समवर्ती कोड को चलने से पहले ही अधिक विश्वसनीय बनाता है।
struct UserProfile: Sendable {
let name: String
let age: Int
}
class NonSendableClass {
var counter: Int = 0
}
उदाहरण में, UserProfile को थ्रेड्स के बीच सुरक्षित रूप से स्थानांतरित किया जा सकता है क्योंकि यह Sendable प्रकारों के स्थिर गुणों वाला एक स्ट्रक्ट है। NonSendableClass await के माध्यम से या Task में स्थानांतरित करने का प्रयास करने पर संकलन त्रुटि उत्पन्न करेगा।
Sendable प्रकार Swift में तीन श्रेणियों में विभाजित होते हैं: Sendable गुणों वाले वैल्यू प्रकार, अपरिवर्तनीय स्थिति वाले अंतिम वर्ग, और @Sendable से चिह्नित फ़ंक्शन/क्लोज़र। कंपाइलर वैल्यू प्रकारों के लिए स्वचालित रूप से Sendable अनुरूपता का अनुमान लगाता है।
Struct, enum और tuple स्वचालित रूप से Sendable बन जाते हैं यदि उनके सभी गुण और संबद्ध मान भी Sendable हों। यह एक रूढ़िवादी दृष्टिकोण है: यदि कम से कम एक गुण Sendable के अनुरूप नहीं है, तो पूरे प्रकार को सुरक्षित नहीं माना जाएगा।
| प्रकार | Sendable | शर्त |
|---|---|---|
| Struct | हाँ (स्पष्ट घोषणा के बिना) | सभी गुण Sendable हैं |
| Enum | हाँ (स्पष्ट घोषणा के बिना) | सभी संबद्ध मान Sendable हैं |
| Final class | हाँ (स्पष्ट घोषणा के साथ) | सभी let गुण Sendable हैं, कोई var नहीं |
| Non-final class | नहीं | वंशानुक्रम के कारण Sendable नहीं हो सकता |
सभी अंतर्निर्मित Swift प्रकार — Int, String, Double, Bool, Optional, Array, Dictionary, Set — Sendable के अनुरूप हैं। यह प्रकार संरचना को डिफ़ॉल्ट रूप से सुरक्षित बनाता है। डेवलपर को केवल कस्टम वर्गों पर ध्यान देना होता है।
@unchecked Sendable एक तंत्र है जो एक वर्ग को कंपाइलर जाँच को दरकिनार करते हुए स्पष्ट रूप से स्वयं को Sendable घोषित करने की अनुमति देता है। डेवलपर ऐसे वर्ग की थ्रेड सुरक्षा की जिम्मेदारी लेता है। यह Objective-C ब्रिज और अनुकूलित संरचनाओं के लिए उपयोगी है।
@unchecked Sendable का उपयोग तब किया जाता है जब कोई वर्ग आंतरिक रूप से लॉक या परमाणु संचालन के माध्यम से सुरक्षा सुनिश्चित करता है, लेकिन कंपाइलर इसे स्थिर रूप से सत्यापित नहीं कर सकता। उदाहरण के लिए, os_unfair_lock या pthread_mutex_t वाला वर्ग — इसकी थ्रेड सुरक्षा कोड द्वारा सुनिश्चित की जाती है, लेकिन Swift इसे नहीं देखता।
final class AtomicCounter: @unchecked Sendable {
private var value: Int = 0
private let lock = NSLock()
func increment() {
lock.lock()
value += 1
lock.unlock()
}
}
@unchecked Sendable का उपयोग सावधानी से किया जाना चाहिए। यह अन्य डेवलपर्स को एक स्पष्ट संकेत है: «मैंने जाँच लिया, यह सुरक्षित है।» कार्यान्वयन में त्रुटि से पकड़ में न आने वाली रेस हो सकती हैं। @unchecked का उपयोग करने से पहले, सुनिश्चित करें कि प्रकार को वास्तव में वैल्यू प्रकार के रूप में फिर से नहीं लिखा जा सकता।
Actor और Sendable एक ही सिक्के के दो पहलू हैं। Actor अपनी स्थिति को अलग करता है, लेकिन बाहरी दुनिया के साथ डेटा आदान-प्रदान करने के लिए उसे Sendable प्रकार लौटाने होंगे। यदि कोई actor विधि गैर-Sendable प्रकार लौटाती है, तो कंपाइलर चेतावनी या त्रुटि देता है।
जब कोई actor बाहरी कोड को डेटा भेजता है, तो यह डेटा अलगाव सीमा को पार करता है। Sendable गारंटी देता है कि प्राप्तकर्ता actor के बाहर इसका सुरक्षित रूप से उपयोग कर सकता है। Actor स्वयं पृथक रहता है — इसकी आंतरिक स्थिति उजागर नहीं होती।
struct AccountSnapshot: Sendable {
let id: UUID
let balance: Double
let lastUpdated: Date
}
actor BankActor {
private var balance: Double = 0
func snapshot() async -> AccountSnapshot {
return AccountSnapshot(
id: UUID(),
balance: balance,
lastUpdated: Date()
)
}
}
AccountSnapshot एक Sendable स्ट्रक्ट है जिसमें केवल Sendable प्रकारों के let गुण हैं। यह दृष्टिकोण actor से डेटा निकालने के लिए सर्वोत्तम अभ्यास है। स्थिति का स्नैपशॉट मान द्वारा स्थानांतरित किया जाता है, और actor अपनी स्थिति पर नियंत्रण नहीं खोता।
@Sendable फ़ंक्शन और क्लोज़र के लिए एक विशेषता है जो गारंटी देती है कि क्लोज़र गैर-Sendable डेटा को परिवर्तनीय रूप में कैप्चर नहीं करता। जब कोई क्लोज़र Task या actor विधि में स्थानांतरित किया जाता है, तो उसे Sendable होना चाहिए।
कंपाइलर जाँचता है कि @Sendable क्लोज़र वर्गों के परिवर्तनीय संदर्भ कैप्चर नहीं करता। Sendable प्रकारों के let गुणों को कैप्चर करने की अनुमति है। संदर्भ प्रकार के var चर को कैप्चर करने से त्रुटि होगी क्योंकि क्लोज़र को उत्परिवर्तन के साथ एक साथ निष्पादित किया जा सकता है।
func performAsync(operation: @Sendable () -> Void) {
Task {
await operation()
}
}
let constant = "Safe"
var counter = 0
// counter — var को कैप्चर करने से counter उत्परिवर्तित होता है, संकलन त्रुटि
performAsync { // ❌ कैप्चर किए गए चर का उत्परिवर्तन
print(constant)
}
नियम सरल है: @Sendable क्लोज़र केवल उन डेटा को कैप्चर कर सकता है जो स्वयं Sendable हैं और बाहर से उत्परिवर्तित नहीं होंगे। वर्गों के लिए, कमजोर संदर्भ weak self को कैप्चर करने की अनुमति है यदि वर्ग Sendable के रूप में चिह्नित नहीं है। यह क्लासिक रिटेन साइकल और रेस कंडीशन को रोकता है।
अक्सर पूछे जाने वाले प्रश्न
Sendable एक मार्कर है जो कंपाइलर को बताता है: «इस प्रकार को थ्रेड्स के बीच सुरक्षित रूप से स्थानांतरित किया जा सकता है।» स्ट्रक्ट और स्थिरांक आमतौर पर डिफ़ॉल्ट रूप से Sendable होते हैं, वर्ग तब तक नहीं जब तक स्पष्ट रूप से निर्दिष्ट न किया जाए।
वैल्यू प्रकार (struct, enum) Sendable गुणों के साथ, अपरिवर्तनीय स्थिति वाले अंतिम वर्ग, और सभी मूल Swift प्रकार: Int, String, Double, Bool, Array, Dictionary, Optional — स्वचालित रूप से Sendable के अनुरूप हैं।
@unchecked Sendable कंपाइलर की स्थिर जाँच के बिना किसी वर्ग को Sendable घोषित करने का एक तरीका है। डेवलपर स्वयं सुरक्षा सुनिश्चित करता है, अक्सर लॉक या परमाणु संचालन के माध्यम से।
Actor अपनी स्थिति को अलग करता है, लेकिन बाहरी कोड को डेटा लौटाते समय, यह डेटा अलगाव सीमा को पार करता है। Sendable गारंटी देता है कि प्राप्तकर्ता को actor के बाहर इस डेटा का उपयोग करते समय रेस का सामना नहीं करना पड़ेगा।
एक अंतिम वर्ग में Sendable प्रोटोकॉल जोड़ें, जिसके सभी गुण Sendable प्रकारों के स्थिरांक हों। यदि वर्ग लॉक का उपयोग करता है, तो @unchecked Sendable का उपयोग किया जा सकता है, लेकिन इसके लिए सावधानी की आवश्यकता है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें