मॉडल थ्रेडिंग

oneway के तौर पर मार्क किए गए तरीकों को ब्लॉक नहीं किया जाता. oneway के तौर पर मार्क नहीं किए गए तरीकों के लिए, क्लाइंट का तरीका कॉल तब तक ब्लॉक रहता है, जब तक सर्वर को पूरा नहीं कर लिया जाता या सिंक्रोनस कॉलबैक को कॉल नहीं किया जाता. सर्वर के तरीके को लागू करने पर, ज़्यादा से ज़्यादा एक सिंक्रोनस कॉलबैक कॉल किया जा सकता है. अतिरिक्त कॉलबैक कॉल को खारिज कर दिया जाता है और गड़बड़ियों के तौर पर लॉग किया जाता है. अगर किसी तरीके को कॉलबैक के ज़रिए वैल्यू दिखानी है और वह अपना कॉलबैक नहीं करता है, तो इसे गड़बड़ी के तौर पर लॉग किया जाता है और क्लाइंट को ट्रांसपोर्ट गड़बड़ी के तौर पर रिपोर्ट किया जाता है.

पास-थ्रू मोड में थ्रेड

पासथ्रू मोड में, ज़्यादातर कॉल सिंक होते हैं. हालांकि, oneway कॉल से क्लाइंट को ब्लॉक न करने के लिए, हर प्रोसेस के लिए एक थ्रेड बनाई जाती है. ज़्यादा जानकारी के लिए, HIDL की खास जानकारी देखें.

बाइंडर वाले एचएएल में थ्रेड

इनकमिंग आरपीसी कॉल (इनमें एचएएल से एचएएल उपयोगकर्ताओं के लिए असाइनोक्रोनस कॉलबैक भी शामिल हैं) और डेथ नोटिफ़िकेशन देने के लिए, HIDL का इस्तेमाल करने वाली हर प्रोसेस के साथ एक थ्रेडपूल जुड़ा होता है. अगर कोई प्रोसेस एक से ज़्यादा HIDL इंटरफ़ेस और/या डिवाइस के बंद होने की सूचना देने वाले हैंडलर लागू करती है, तो उसका थ्रेडपूल उन सभी के बीच शेयर किया जाता है. जब किसी प्रोसेस को क्लाइंट से कोई इनकमिंग मेथड कॉल मिलता है, तो वह थ्रेडपूल से कोई खाली थ्रेड चुनती है और उस थ्रेड पर कॉल को लागू करती है. अगर कोई खाली थ्रेड उपलब्ध नहीं है, तो यह तब तक ब्लॉक रहता है, जब तक कोई थ्रेड उपलब्ध नहीं हो जाती.

अगर सर्वर में सिर्फ़ एक थ्रेड है, तो सर्वर में कॉल, क्रम से पूरे किए जाते हैं. एक से ज़्यादा थ्रेड वाला सर्वर, कॉल को क्रम से पूरा नहीं कर सकता. भले ही, क्लाइंट में सिर्फ़ एक थ्रेड हो. हालांकि, किसी इंटरफ़ेस ऑब्जेक्ट के लिए, oneway कॉल के क्रम में होने की गारंटी होती है (सर्वर थ्रेडिंग मॉडल देखें). एक से ज़्यादा थ्रेड वाले सर्वर के लिए, जो कई इंटरफ़ेस होस्ट करता है, अलग-अलग इंटरफ़ेस के oneway कॉल को एक साथ या ब्लॉक करने वाले अन्य कॉल के साथ प्रोसेस किया जा सकता है.

एक ही hwbinder थ्रेड पर कई नेस्ट किए गए कॉल भेजे जाते हैं. उदाहरण के लिए, अगर कोई प्रोसेस (A) hwbinder थ्रेड से प्रोसेस (B) में सिंक्रोनस कॉल करती है और फिर प्रोसेस (B) प्रोसेस (A) में सिंक्रोनस कॉल करती है, तो कॉल (A) में मूल hwbinder थ्रेड पर लागू होता है, जो मूल कॉल पर ब्लॉक होता है. इस ऑप्टिमाइज़ेशन की मदद से, नेस्ट किए गए कॉल को मैनेज करने के लिए, एक थ्रेड वाला सर्वर इस्तेमाल किया जा सकता है. हालांकि, यह उन मामलों में काम नहीं करता जहां कॉल, आईपीसी कॉल के किसी दूसरे क्रम से यात्रा करते हैं. उदाहरण के लिए, अगर प्रोसेस (B) ने एक ऐसा binder/vndbinder कॉल किया है जिसने प्रोसेस (C) को कॉल किया है और फिर प्रोसेस (C) ने (A) में वापस कॉल किया है, तो इसे (A) में मूल थ्रेड पर नहीं दिखाया जा सकता.

सर्वर थ्रेडिंग मॉडल

पासथ्रू मोड को छोड़कर, HIDL इंटरफ़ेस के सर्वर लागू करने की प्रोसेस, क्लाइंट से अलग होती है. साथ ही, इनमें एक या उससे ज़्यादा थ्रेड की ज़रूरत होती है, जो आने वाले तरीकों के कॉल के लिए इंतज़ार करते हैं. ये थ्रेड, सर्वर के थ्रेडपूल होते हैं. सर्वर यह तय कर सकता है कि उसके थ्रेडपूल में कितनी थ्रेड चलनी हैं. साथ ही, अपने इंटरफ़ेस पर सभी कॉल को क्रम से लगाने के लिए, एक थ्रेडपूल साइज़ का इस्तेमाल कर सकता है. अगर सर्वर के थ्रेडपूल में एक से ज़्यादा थ्रेड हैं, तो उसे अपने किसी भी इंटरफ़ेस पर एक साथ कई इनकमिंग कॉल मिल सकते हैं. C++ में इसका मतलब है कि शेयर किए गए डेटा को सावधानी से लॉक किया जाना चाहिए.

एक ही इंटरफ़ेस में एकतरफ़ा कॉल को क्रम से लगाया जाता है. अगर कोई मल्टी-थ्रेड वाला क्लाइंट, इंटरफ़ेस IFoo पर method1 और method2 और इंटरफ़ेस IBar पर method3 को कॉल करता है, तो method1 और method2 को हमेशा क्रम से चलाया जाता है. हालांकि, method3 को method1 और method2 के साथ-साथ चलाया जा सकता है.

एक क्लाइंट थ्रेड के एक साथ कई थ्रेड वाले सर्वर पर एक साथ प्रोसेस होने की दो वजहें हो सकती हैं:

  • oneway कॉल ब्लॉक नहीं होते. अगर oneway कॉल के बाद कोई ऐसा कॉल किया जाता है जो oneway कॉल नहीं है, तो सर्वर एक साथ oneway कॉल और नॉन-oneway कॉल को पूरा कर सकता है.
  • सर्वर के ऐसे तरीके जो सिंक्रोनस कॉलबैक के साथ डेटा वापस भेजते हैं, सर्वर से कॉलबैक का इस्तेमाल होते ही क्लाइंट को अनब्लॉक कर सकते हैं.

दूसरे तरीके के लिए, सर्वर फ़ंक्शन में मौजूद कोई भी कोड, कॉलबैक के बाद एक साथ चल सकता है. साथ ही, सर्वर क्लाइंट से आने वाले बाद के कॉल को मैनेज करता है. इसमें सर्वर फ़ंक्शन और फ़ंक्शन के आखिर में चलने वाले अपने-आप काम बंद करने वाले डिस्ट्रॉक्टर का कोड शामिल होता है. अगर सर्वर के थ्रेडपूल में एक से ज़्यादा थ्रेड हैं, तो एक ही क्लाइंट थ्रेड से कॉल आने पर भी, एक साथ कई काम करने से जुड़ी समस्याएं आती हैं. (अगर किसी प्रोसेस से सेवा देने वाले किसी भी एचएएल को कई थ्रेड की ज़रूरत है, तो सभी एचएएल में कई थ्रेड होते हैं, क्योंकि थ्रेडपूल को हर प्रोसेस के साथ शेयर किया जाता है.)

जैसे ही सर्वर, दिए गए कॉलबैक को कॉल करता है, ट्रांसपोर्ट क्लाइंट पर लागू किए गए कॉलबैक को कॉल कर सकता है और क्लाइंट को अनब्लॉक कर सकता है. क्लाइंट, कॉलबैक को कॉल करने के बाद, सर्वर के लागू होने के साथ-साथ आगे बढ़ता है. इसमें डेस्ट्रक्टर चलाना भी शामिल हो सकता है. कॉलबैक के बाद, सर्वर फ़ंक्शन में मौजूद कोड, क्लाइंट को ब्लॉक नहीं करता. ऐसा तब तक होता है, जब तक सर्वर थ्रेडपूल में इनकमिंग कॉल को हैंडल करने के लिए ज़रूरी थ्रेड मौजूद हों. हालांकि, इसे क्लाइंट से आने वाले आने वाले कॉल के साथ एक साथ चलाया जा सकता है. ऐसा तब तक होता है, जब तक सर्वर थ्रेडपूल में सिर्फ़ एक थ्रेड मौजूद न हो.

सिंक्रोनस कॉलबैक के अलावा, एक-थ्रेड वाले क्लाइंट से किए गए oneway कॉल को, थ्रेडपूल में कई थ्रेड वाले सर्वर से एक साथ मैनेज किया जा सकता है. हालांकि, ऐसा सिर्फ़ तब किया जा सकता है, जब वे oneway कॉल अलग-अलग इंटरफ़ेस पर किए गए हों. एक ही इंटरफ़ेस पर oneway कॉल हमेशा क्रम से होते हैं.

ध्यान दें: हमारा सुझाव है कि सर्वर फ़ंक्शन, कॉलबैक फ़ंक्शन को कॉल करने के तुरंत बाद रिटर्न कर दें.

उदाहरण के लिए (C++ में):

Return<void> someMethod(someMethod_cb _cb) {
    // Do some processing, then call callback with return data
    hidl_vec<uint32_t> vec = ...
    _cb(vec);
    // At this point, the client's callback is called,
    // and the client resumes execution.
    ...
    return Void(); // is basically a no-op
};

क्लाइंट थ्रेडिंग मॉडल

क्लाइंट पर थ्रेडिंग मॉडल, नॉन-ब्लॉकिंग कॉल (oneway कीवर्ड से मार्क किए गए फ़ंक्शन) और ब्लॉकिंग कॉल (oneway कीवर्ड से मार्क नहीं किए गए फ़ंक्शन) के बीच अलग-अलग होता है.

कॉल ब्लॉक करना

कॉल ब्लॉक करने के लिए, क्लाइंट तब तक ब्लॉक करता है, जब तक इनमें से कोई एक काम नहीं हो जाता:

  • ट्रांसपोर्ट से जुड़ी गड़बड़ी होती है; Return ऑब्जेक्ट में गड़बड़ी की एक स्थिति होती है, जिसे Return::isOk() की मदद से वापस पाया जा सकता है.
  • सर्वर लागू होने पर, कॉलबैक को कॉल किया जाता है (अगर कोई कॉलबैक था).
  • अगर कोई कॉलबैक पैरामीटर नहीं है, तो सर्वर लागू करने पर कोई वैल्यू दिखती है.

अगर फ़ंक्शन सही तरीके से काम करता है, तो फ़ंक्शन के रिटर्न होने से पहले, सर्वर हमेशा उस कॉलबैक फ़ंक्शन को कॉल करता है जिसे क्लाइंट ने आर्ग्युमेंट के तौर पर पास किया है. कॉलबैक को उसी थ्रेड पर लागू किया जाता है जिस पर फ़ंक्शन कॉल किया जाता है. इसलिए, इसे लागू करने वाले लोगों को फ़ंक्शन कॉल के दौरान लॉक को होल्ड करने में सावधानी बरतनी चाहिए. अगर हो सके, तो लॉक का इस्तेमाल बिलकुल न करें. generates स्टेटमेंट या oneway कीवर्ड के बिना कोई फ़ंक्शन अब भी ब्लॉक कर रहा है. क्लाइंट तब तक ब्लॉक करता है, जब तक कि सर्वर Return<void> ऑब्जेक्ट नहीं दिखाता.

एकतरफ़ा कॉल

जब किसी फ़ंक्शन को oneway के तौर पर मार्क किया जाता है, तो क्लाइंट तुरंत रिटर्न करता है और सर्वर के फ़ंक्शन कॉल को पूरा करने का इंतज़ार नहीं करता. इसका मतलब है कि फ़ंक्शन कॉल में आधा समय लगता है, क्योंकि यह आधा कोड एक्ज़ीक्यूट कर रहा है. हालांकि, परफ़ॉर्मेंस पर असर डालने वाले लागू करने के तरीके लिखते समय, शेड्यूलिंग पर इसका कुछ असर पड़ता है. आम तौर पर, एकतरफ़ा कॉल का इस्तेमाल करने पर, कॉल करने वाले व्यक्ति को शेड्यूल किया जाता रहता है. वहीं, सामान्य सिंक्रोनस कॉल का इस्तेमाल करने पर, शेड्यूलर कॉल करने वाले व्यक्ति से कॉल पाने वाले व्यक्ति की प्रोसेस पर तुरंत ट्रांसफ़र हो जाता है. यह बिंडर में परफ़ॉर्मेंस ऑप्टिमाइज़ेशन है. जिन सेवाओं के लिए टारगेट प्रोसेस में वन-वे कॉल को ज़्यादा प्राथमिकता के साथ चलाना ज़रूरी है उनके लिए, कॉल पाने वाली सेवा की शेड्यूलिंग नीति में बदलाव किया जा सकता है. C++ में, sched.h में बताई गई शेड्यूलर की प्राथमिकताओं और नीतियों के साथ libhidltransport के तरीके setMinSchedulerPolicy का इस्तेमाल करने से यह पक्का होता है कि सेवा में किए गए सभी कॉल, कम से कम शेड्यूलिंग की सेट की गई नीति और प्राथमिकता के हिसाब से चलते हैं.