แบบเกลียว

วิธีการที่ถูกทำเครื่องหมายว่าเป็น 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 ทั้งหมดจะมีหลายเธรดเนื่องจากเธรดพูลถูกแชร์ต่อกระบวนการ)

ทันทีที่เซิร์ฟเวอร์เรียกการเรียกกลับที่ให้มา การขนส่งสามารถเรียกการเรียกกลับที่นำไปใช้บนไคลเอนต์และปลดบล็อกไคลเอนต์ได้ ไคลเอนต์ดำเนินการควบคู่ไปกับสิ่งที่การใช้งานเซิร์ฟเวอร์ทำหลังจากเรียกการเรียกกลับ (ซึ่งอาจรวมถึงการรัน destructors) รหัสในฟังก์ชันเซิร์ฟเวอร์หลังจากการเรียกกลับไม่ได้บล็อกไคลเอนต์อีกต่อไป (ตราบใดที่เซิร์ฟเวอร์เธรดพูลมีเธรดเพียงพอที่จะจัดการสายเรียกเข้า) แต่อาจถูกดำเนินการพร้อมกันกับการเรียกในอนาคตจากไคลเอนต์ (เว้นแต่เธรดพูลของเซิร์ฟเวอร์จะมีเธรดเดียวเท่านั้น ).

นอกเหนือจากการเรียกกลับแบบซิงโครนัสแล้ว การเรียกแบบ 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 will be called,
    // and the client will resume execution.
    ...
    return Void(); // is basically a no-op
};

โมเดลการเธรดไคลเอ็นต์

โมเดลเธรดบนไคลเอนต์แตกต่างกันระหว่างการโทรที่ไม่บล็อค (ฟังก์ชันที่ทำเครื่องหมายด้วยคีย์เวิร์ด oneway ) และการบล็อคการโทร (ฟังก์ชันที่ไม่ได้ระบุคีย์เวิร์ด oneway )

การปิดกั้นการโทร

สำหรับการบล็อกการโทร ไคลเอนต์จะบล็อกจนกว่าจะเกิดเหตุการณ์ใดเหตุการณ์หนึ่งต่อไปนี้:

  • เกิดข้อผิดพลาดในการขนส่ง วัตถุ Return มีสถานะข้อผิดพลาดที่สามารถดึงข้อมูลได้ด้วย Return::isOk()
  • การใช้งานเซิร์ฟเวอร์เรียกการโทรกลับ (ถ้ามี)
  • การใช้งานเซิร์ฟเวอร์ส่งคืนค่า (หากไม่มีพารามิเตอร์การเรียกกลับ)

ในกรณีที่สำเร็จ ฟังก์ชันการเรียกกลับที่ไคลเอ็นต์ส่งผ่านเป็นอาร์กิวเมนต์จะถูกเรียกโดยเซิร์ฟเวอร์เสมอก่อนที่ฟังก์ชันจะส่งคืน การเรียกกลับจะดำเนินการบนเธรดเดียวกันกับที่มีการเรียกใช้ฟังก์ชัน ดังนั้นผู้นำไปใช้งานจะต้องระมัดระวังในการล็อคค้างไว้ระหว่างการเรียกใช้ฟังก์ชัน (และหลีกเลี่ยงทั้งหมดเมื่อเป็นไปได้) ฟังก์ชันที่ไม่มีคำสั่ง generates หรือคีย์เวิร์ด oneway ยังคงบล็อกอยู่ ไคลเอนต์บล็อกจนกว่าเซิร์ฟเวอร์ส่งคืนวัตถุ Return<void>

โทรวันเวย์

เมื่อฟังก์ชันถูกทำเครื่องหมาย oneway ไคลเอ็นต์จะกลับมาทันทีและไม่รอให้เซิร์ฟเวอร์ทำการเรียกใช้ฟังก์ชันให้เสร็จสิ้น โดยสรุป (และโดยรวม) นี่หมายความว่าการเรียกใช้ฟังก์ชันใช้เวลาเพียงครึ่งเดียวเนื่องจากกำลังรันโค้ดเพียงครึ่งเดียว แต่เมื่อเขียนการใช้งานที่คำนึงถึงประสิทธิภาพ การดำเนินการนี้จะมีผลกระทบต่อกำหนดการบางประการ โดยปกติ การใช้การโทรแบบทางเดียวจะทำให้ผู้เรียกถูกกำหนดเวลาต่อไป ในขณะที่การใช้การโทรแบบซิงโครนัสปกติจะทำให้ตัวกำหนดเวลาถ่ายโอนจากผู้เรียกไปยังกระบวนการของผู้เรียกทันที นี่คือการปรับประสิทธิภาพให้เหมาะสมที่สุดในเครื่องผูก สำหรับบริการที่ต้องดำเนินการการโทรแบบเที่ยวเดียวในกระบวนการเป้าหมายที่มีลำดับความสำคัญสูง นโยบายการจัดกำหนดการของบริการที่รับสามารถเปลี่ยนแปลงได้ ใน C ++ การใช้เมธอด setMinSchedulerPolicy ของ libhidltransport กับลำดับความสำคัญของตัวกำหนดเวลาและนโยบายที่กำหนดใน sched.h ช่วยให้มั่นใจได้ว่าการโทรเข้าสู่บริการทั้งหมดจะทำงานอย่างน้อยตามนโยบายและลำดับความสำคัญของการกำหนดตารางเวลาที่ตั้งไว้