דגמי השחלה

שיטות המסומנות oneway אינן חוסמות. עבור שיטות שאינן מסומנות כ- oneway , קריאת השיטה של ​​לקוח תיחסם עד שהשרת סיים את הביצוע או יקרא התקשרות חוזרת סינכרונית (המוקדם מביניהם). יישומי שיטת שרת עשויים לקרוא לכל היותר התקשרות חוזרת סינכרונית אחת; שיחות התקשרות חוזרות נוספות נמחקות ונרשמות כשגיאות. אם שיטה אמורה להחזיר ערכים באמצעות התקשרות חוזרת ואינה קוראת להתקשרות חוזרת, הדבר נרשם כשגיאה ומדווח כשגיאת העברה ללקוח.

שרשורים במצב מעבר

במצב מעבר, רוב השיחות הן סינכרוניות. עם זאת, כדי לשמר את ההתנהגות המיועדת לכך ששיחות oneway אינן חוסמות את הלקוח, נוצר שרשור עבור כל תהליך. לפרטים, עיין בסקירה הכללית של HIDL .

חוטים ב-HAL משולבים

כדי לשרת שיחות RPC נכנסות (כולל התקשרות א-סינכרונית מ-HALs למשתמשי HAL) והודעות מוות, מאגר אשכול משויך לכל תהליך המשתמש ב-HIDL. אם תהליך בודד מיישם ממשקי HIDL מרובים ו/או מטפלים בהודעת מוות, מאגר השרשור שלו משותף בין כולם. כאשר תהליך מקבל קריאת שיטה נכנסת מלקוח, הוא בוחר פתיל פנוי מ-threadpool ומבצע את השיחה באותו פתיל. אם אין שרשור פנוי זמין, הוא נחסם עד שהוא זמין.

אם לשרת יש רק שרשור אחד, הקריאות אל השרת מושלמות לפי הסדר. שרת עם יותר משרשור אחד עלול להשלים שיחות שלא בסדר גם אם ללקוח יש רק חוט אחד. עם זאת, עבור אובייקט ממשק נתון, שיחות oneway מובטחות שיוזמנו (ראה מודל השרשור של שרת ). עבור שרת מרובה פתילים המארח ממשקים מרובים, שיחות oneway לממשקים שונים עשויות להיות מעובדות במקביל זו לזו או שיחות חסימה אחרות.

שיחות מקוננות מרובות יישלחו באותו חוט של hwbinder. לדוגמה, אם תהליך (A) מבצע קריאה סינכרונית משרשור hwbinder לתהליך (B), ולאחר מכן תהליך (B) מבצע קריאה סינכרונית חזרה לתהליך (A), הקריאה תתבצע בשרשור hwbinder המקורי ב (A) אשר חסום בשיחה המקורית. אופטימיזציה זו מאפשרת לקבל שרת פתיל יחיד המסוגל לטפל בשיחות מקוננות, אך היא אינה מתרחבת למקרים בהם השיחות עוברות דרך רצף אחר של שיחות IPC. לדוגמה, אם תהליך (B) ביצע קריאת מקשר/vndbinder שהתקשרה לתהליך (C) ולאחר מכן תהליך (C) קורא חזרה ל-(A), לא ניתן להגיש אותו בשרשור המקורי ב-(A).

דגם השחלת שרת

מלבד מצב מעבר, יישומי שרת של ממשקי HIDL חיים בתהליך שונה מהלקוח וצריכים שרשור אחד או יותר הממתין לקריאת שיטה נכנסת. שרשורים אלה הם מאגר השרשורים של השרת; השרת עשוי להחליט כמה שרשורים הוא רוצה שיפעלו ב-Threadpool שלו, ויכול להשתמש ב-Threadpool בגודל של אחד כדי לבצע סדרה של כל השיחות בממשקיו. אם לשרת יש יותר מ-thread אחד ב-Threadpool, הוא יכול לקבל שיחות נכנסות במקביל בכל אחד מהממשקים שלו (ב-C++, זה אומר שיש לנעול נתונים משותפים בזהירות).

שיחות חד-כיווניות לאותו ממשק עוברות בסידרה. אם לקוח מרובה הליכי קורא method1 ו- method2 בממשק IFoo , ו- method3 בממשק IBar , method1 ו- method2 תמיד יהיו מסודרות, אבל method3 עשויה לפעול במקביל ל- method1 ו- method2 .

פתיל ביצוע של לקוח בודד יכול לגרום לביצוע במקביל בשרת עם מספר פתילים בשתי דרכים:

  • שיחות oneway אינן חוסמות. אם מבוצעת קריאה oneway ולאחר מכן נקראת קריאה שאינה oneway , השרת עשוי לבצע את השיחה oneway והקריאה הלא- oneway בו-זמנית.
  • שיטות שרת המעבירות נתונים בחזרה עם התקשרויות סינכרוניות יכולות לבטל את חסימת הלקוח ברגע שהקריאה חוזרת נקראת מהשרת.

בדרך השנייה, כל קוד בפונקציית השרת שפועל לאחר קריאת ה-callback עשוי לפעול במקביל, כאשר השרת מטפל בקריאות עוקבות מהלקוח. זה כולל קוד בפונקציית השרת ומשמידים אוטומטיים המופעלים בסוף הפונקציה. אם לשרת יש יותר משרשור אחד ב-Threadpool שלו, בעיות במקביל מתעוררות גם אם נכנסות שיחות רק משרשור לקוח אחד בודד. (אם כל HAL שמוגש על ידי תהליך צריך שרשורים מרובים, לכל ה-HALs יהיו שרשורים מרובים מכיוון שה-Threadpool משותף לכל תהליך.)

ברגע שהשרת קורא ל-callback שסופק, התחבורה יכולה לקרוא ל-callback המיושם בלקוח ולבטל את חסימת הלקוח. הלקוח ממשיך במקביל לכל מה שהטמעת השרת עושה לאחר שהוא קורא ל-callback (שעשוי לכלול הרס הורסים). הקוד בפונקציית השרת לאחר ההתקשרות לאחור כבר לא חוסם את הלקוח (כל עוד ל-Threadpool של השרת יש מספיק פתילים כדי לטפל בקריאות נכנסות), אבל הוא עשוי להתבצע במקביל לקריאות עתידיות מהלקוח (אלא אם ל-Threadpool של השרת יש רק פתיל אחד ).

בנוסף להתקשרות חוזרת סינכרונית, שיחות oneway מלקוח עם פתיל בודד עשויות להיות מטופלות במקביל על-ידי שרת עם מספר פתילים ב-Threadpool שלו, אך רק אם שיחות 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 will be called,
    // and the client will resume execution.
    ...
    return Void(); // is basically a no-op
};

דגם השחלת לקוח

מודל השרשור בלקוח שונה בין שיחות שאינן חוסמות (פונקציות המסומנות במילת המפתח oneway ) לבין שיחות חסימת (פונקציות שאין להן מילת המפתח oneway שצוינה).

חסימת שיחות

עבור חסימת שיחות, הלקוח חוסם עד שאחד מהדברים הבאים קורה:

  • מתרחשת שגיאת תחבורה; האובייקט Return מכיל מצב שגיאה שניתן לאחזר באמצעות Return::isOk() .
  • יישום שרת קורא להתקשרות חזרה (אם היה כזה).
  • הטמעת שרת מחזירה ערך (אם לא היה פרמטר התקשרות חוזרת).

במקרה של הצלחה, פונקציית ה-callback שהלקוח מעביר כארגומנט נקראת תמיד על ידי השרת לפני שהפונקציה עצמה חוזרת. ההתקשרות חוזרת מתבצעת באותו שרשור שבו מתבצעת קריאת הפונקציה, ולכן המיישמים חייבים להיות זהירים בהחזקת מנעולים במהלך קריאות פונקציה (ולהימנע מהם לחלוטין כשאפשר). פונקציה ללא הצהרה generates או מילת מפתח oneway עדיין חוסמת; הלקוח חוסם עד שהשרת מחזיר אובייקט Return<void> .

שיחות חד-כיווניות

כאשר פונקציה מסומנת oneway , הלקוח חוזר מיד ואינו ממתין עד שהשרת ישלים את קריאת הפונקציה שלו. על פני השטח (ובמצטבר), זה אומר שהקריאה לפונקציה לוקחת חצי מהזמן מכיוון שהיא מבצעת חצי מהקוד, אבל כשכותבים יישומים שהם רגישים לביצועים, יש לזה השלכות על תזמון. בדרך כלל, שימוש בשיחה חד-כיוונית גורם למתקשר להמשיך לתזמן בעוד ששימוש בשיחה סינכרונית רגילה גורם למתזמן לעבור מיד מהמתקשר לתהליך המתקשר. זהו אופטימיזציה של ביצועים בקלסר. עבור שירותים שבהם יש לבצע את השיחה החד-כיוונית בתהליך היעד בעדיפות גבוהה, ניתן לשנות את מדיניות התזמון של השירות המקבל. ב-C++, שימוש בשיטה setMinSchedulerPolicy של libhidltransport עם סדרי העדיפויות והמדיניות של מתזמן המוגדרים ב- sched.h מבטיח שכל הקריאות לשירות יפעלו לפחות לפי מדיניות התזמון והעדיפות שנקבעו.