روشهای علامتگذاریشده بهعنوان oneway مسدود نمیشوند. برای روشهایی که بهعنوان
oneway علامتگذاری نشدهاند، تا زمانی که سرور اجرای آن را تکمیل نکرده باشد یا یک برگشت همزمان را فراخوانی نکرده باشد (هرکدام زودتر اتفاق بیفتد)، فراخوانی روش مشتری مسدود میشود.
پیادهسازیهای روش سرور میتوانند حداکثر یک فراخوانی برگشتی همگام را فراخوانی کنند؛
فراخوانیهای برگشتی اضافی نادیده گرفته میشوند و بهعنوان خطا ثبت میشوند. اگر روشی قرار باشد مقادیر را ازطریق تماس برگشتی برگرداند و تماس برگشتی خود را فراخوانی نکند، این مورد بهعنوان خطا ثبت میشود و بهعنوان خطای انتقال به مشتری گزارش میشود.
رشتهها در حالت عبور
در حالت انتقال، اکثر تماسها همزمان هستند. بااینحال، برای حفظ
رفتار موردنظر که تماسهای oneway کارخواه را مسدود نمیکنند،
رشتهای برای هر فرایند ایجاد میشود. برای جزئیات،
نمای کلی HIDL را ببینید.
رشتهها در HALهای دستهبندیشده
برای ارائه تماسهای ورودی RPC (ازجمله بازخوانهای ناهمزمان از HAL به کاربران HAL) و اعلانهای مرگ، یک استخر نخ با هر فرایندی که از HIDL استفاده میکند مرتبط میشود. اگر یک فرایند چندین میانای HIDL و/یا مدیران اعلان مرگ را پیادهسازی کند، استخر نخ آن بین همه آنها همرسانی میشود. وقتی فرایندی فراخوانی روش ورودی را از کارخواه دریافت میکند، رشتهای آزاد را از استخر رشته انتخاب میکند و فراخوانی را در آن رشته اجرا میکند. اگر رشته آزادی دردسترس نباشد، تا زمانی که رشتهای دردسترس قرار گیرد مسدود میشود.
اگر سرور فقط یک رشته داشته باشد، تماسهای ورودی به سرور بهترتیب تکمیل میشوند. سروری که بیشاز یک رشته دارد ممکن است تماسها را بدون ترتیب تکمیل کند
حتی اگر کارخواه فقط یک رشته داشته باشد. بااینحال، برای یک شیء واسط معین،
ترتیب فراخوانیهای oneway تضمین میشود (به
مدل رشتهبندی سرور مراجعه کنید). برای سرور چندرشتهای که
چندین میانای میزبان دارد، oneway فراخوانی به میاناهای مختلف
ممکن است بهطور همزمان با یکدیگر یا با فراخوانیهای مسدودکننده دیگر پردازش شود.
چندین تماس تودرتو در یک رشته hwbinder ارسال میشود. برای مثال، اگر فرایند (A) تماس همگامی از رشته hwbinder به فرایند (B) برقرار کند، و سپس فرایند (B) تماس همگام برگشتی به فرایند (A) برقرار کند، تماس در رشته hwbinder اصلی در (A) که در تماس اصلی مسدود شده است اجرا میشود. این بهینهسازی باعث میشود سرور تکرشتهای بتواند تماسهای تودرتو را مدیریت کند، اما در مواردی که تماسها ازطریق توالی دیگری از تماسهای IPC منتقل میشوند، این بهینهسازی اعمال نمیشود. برای مثال، اگر فرایند (B) فراخوانی binder/vndbinder انجام داده باشد که فرایند (C) را فراخوانی کرده باشد و سپس فرایند (C) دوباره (A) را فراخوانی کند، نمیتواند در رشته اصلی در (A) ارائه شود.
مدل رشتهسازی سرور
بهجز حالت عبوری، پیادهسازیهای سرور از میاناهای HIDL در فرایندی متفاوت از کارخواه قرار دارند و به یک یا چند رشته نیاز دارند که منتظر تماسهای روش ورودی باشند. این رشتهها استخر رشته سرور هستند؛ سرور میتواند تصمیم بگیرد که چند رشته در استخر رشتهاش اجرا شود، و میتواند از استخر رشتهای با اندازه یک برای سریالسازی همه فراخوانیها در میاناهای خود استفاده کند. اگر سرور بیش از یک رشته در استخر رشته داشته باشد، میتواند تماسهای ورودی همزمان را در هریک از میاناهای خود دریافت کند (در C++، این یعنی دادههای همرسانیشده باید بهدقت قفل شوند).
تماسهای یکطرفه به همان میانای کاربری بهصورت سریال درمیآیند. اگر یک کارخواه چندرشتهای
method1 و method2 را در میانای
IFoo، و method3 را در میانای IBar
فراخوانی کند، method1 و method2 همیشه سریالسازی میشوند، اما
method3 میتواند بهموازات method1 و
method2 اجرا شود.
یک رشته اجرای مشتری میتواند به دو روش باعث اجرای همزمان در سرور با چندین رشته شود:
- تماسهای
onewayمسدود نمیشود. اگر تماسonewayاجرا شود و سپس با غیرonewayتماس گرفته شود، سرور میتواند تماسonewayو تماس غیرonewayرا بهطور همزمان اجرا کند. - روشهای سرور که دادهها را با برگشتتماسهای همزمان برمیگردانند میتوانند بهمحض اینکه برگشتتماس از سرور فراخوانی شد، انسداد کارخواه را بردارند.
در روش دوم، هر کدی در تابع سرور که پساز فراخوانی بازخوان اجرا میشود میتواند همزمان اجرا شود و سرور تماسهای بعدی کارخواه را مدیریت میکند. این شامل کد در عملکرد سرور و تخریبکنندههای خودکاری است که در انتهای عملکرد اجرا میشوند. اگر سرور بیشاز یک رشته در استخر رشته خود داشته باشد، حتی اگر تماسها فقط از یک رشته کارخواه واحد دریافت شوند، مشکلات همزمانسازی بهوجود میآیند. (اگر هریک از HALهای ارائهشده توسط یک فرایند به چندین رشته نیاز داشته باشد، همه HALها چندین رشته دارند زیرا استخر رشته بهازای هر فرایند همرسانی میشود.)
بهمحض اینکه سرور فراخوان برگشتی ارائهشده را فراخوانی کند، انتقال میتواند فراخوان برگشتی پیادهسازیشده را در کارخواه فراخوانی کند و کارخواه را رفع انسداد کند. کارخواه بهطور موازی با هر کاری که پیادهسازی سرور پساز فراخوانی callback انجام میدهد (که ممکن است شامل اجرای destructor باشد) ادامه میدهد. کد در تابع سرور پساز اینکه برگشتتماس دیگر مشتری را مسدود نمیکند (تا زمانی که استخر نخ سرور نخهای کافی برای مدیریت تماسهای ورودی داشته باشد)، اما ممکن است همزمان با تماسهای آینده از مشتری اجرا شود (مگر اینکه استخر نخ سرور فقط یک نخ داشته باشد).
علاوهبر تماسهای برگشتی همزمان، تماسهای 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 علامتگذاری میشود، کارخواه بلافاصله برمیگردد
و منتظر نمیماند تا سرور فراخوانی تابع خود را تکمیل کند. در سطح (و بهصورت تجمیعی)، این یعنی فراخوانی تابع نصف زمان میبرد زیرا نصف کد را اجرا میکند، اما هنگام نوشتن پیادهسازیهایی که به عملکرد حساس هستند، این موضوع پیامدهایی برای زمانبندی دارد. معمولاً،
استفاده از تماس یکطرفه باعث میشود تماسگیرنده همچنان زمانبندی شود، درحالیکه
استفاده از تماس همگام عادی باعث میشود زمانبند فوراً از تماسگیرنده به فرایند تماسگیرنده منتقل شود. این بهینهسازی عملکرد در
binder است. برای سرویسهایی که تماس یکطرفه باید در فرایند هدف با اولویت بالا اجرا شود، خطمشی زمانبندی سرویس گیرنده را میتوان تغییر داد. در ++C، استفاده از روش libhidltransport
setMinSchedulerPolicy با اولویتها و خطمشیهای زمانبندی تعریفشده در sched.h تضمین میکند که همه تماسها با سرویس حداقل با خطمشی و اولویت زمانبندی تنظیمشده اجرا شوند.