Model Threading

Metode yang ditandai sebagai oneway tidak memblokir. Untuk metode yang tidak ditandai sebagai oneway , panggilan metode klien akan memblokir hingga server menyelesaikan eksekusi atau disebut panggilan balik sinkron (mana saja yang lebih dulu). Implementasi metode server dapat memanggil paling banyak satu panggilan balik sinkron; panggilan panggilan balik tambahan dibuang dan dicatat sebagai kesalahan. Jika suatu metode seharusnya mengembalikan nilai melalui panggilan balik dan tidak memanggil panggilan baliknya, ini dicatat sebagai kesalahan dan dilaporkan sebagai kesalahan transportasi ke klien.

Utas dalam mode passthrough

Dalam mode passthrough, sebagian besar panggilan bersifat sinkron. Namun, untuk mempertahankan perilaku yang dimaksudkan agar panggilan oneway tidak memblokir klien, utas dibuat untuk setiap proses. Untuk detailnya, lihat ikhtisar HIDL .

Utas dalam HAL yang diikat

Untuk melayani panggilan RPC masuk (termasuk panggilan balik asinkron dari HAL ke pengguna HAL) dan pemberitahuan kematian, kumpulan utas dikaitkan dengan setiap proses yang menggunakan HIDL. Jika satu proses mengimplementasikan beberapa antarmuka HIDL dan/atau penangan pemberitahuan kematian, kumpulan utasnya dibagikan di antara semuanya. Ketika sebuah proses menerima panggilan metode yang masuk dari klien, ia mengambil utas gratis dari kumpulan utas dan mengeksekusi panggilan di utas itu. Jika tidak ada utas gratis yang tersedia, utas akan diblokir hingga tersedia.

Jika server hanya memiliki satu utas, maka panggilan ke server diselesaikan secara berurutan. Server dengan lebih dari satu utas dapat menyelesaikan panggilan yang rusak bahkan jika klien hanya memiliki satu utas. Namun, untuk objek antarmuka tertentu, panggilan oneway dijamin akan dipesan (lihat Model threading Server ). Untuk server multi-utas yang menampung banyak antarmuka, panggilan oneway ke antarmuka yang berbeda dapat diproses secara bersamaan satu sama lain atau panggilan pemblokiran lainnya.

Beberapa panggilan bersarang akan dikirim pada utas hwbinder yang sama. Misalnya, jika suatu proses (A) membuat panggilan sinkron dari utas hwbinder ke proses (B), dan kemudian proses (B) membuat panggilan sinkron kembali ke proses (A), panggilan akan dieksekusi pada utas hwbinder asli di (A) yang diblokir pada panggilan asli. Pengoptimalan ini memungkinkan untuk memiliki satu server berulir yang dapat menangani panggilan bersarang, tetapi tidak meluas ke kasus di mana panggilan berjalan melalui urutan panggilan IPC lainnya. Misalnya, jika proses (B) telah membuat panggilan binder/vndbinder yang dipanggil ke proses (C) dan kemudian proses (C) memanggil kembali ke (A), itu tidak dapat dilayani di utas asli di (A).

Model utas server

Kecuali untuk mode passthrough, implementasi server dari antarmuka HIDL hidup dalam proses yang berbeda dari klien dan membutuhkan satu atau lebih utas yang menunggu panggilan metode yang masuk. Utas ini adalah kumpulan utas server; server dapat memutuskan berapa banyak utas yang ingin dijalankan di kumpulan utasnya, dan dapat menggunakan ukuran utas satu utas untuk membuat serial semua panggilan pada antarmukanya. Jika server memiliki lebih dari satu utas di kumpulan utas, server dapat menerima panggilan masuk bersamaan di salah satu antarmukanya (dalam C++, ini berarti bahwa data yang dibagikan harus dikunci dengan hati-hati).

Panggilan satu arah ke antarmuka yang sama diserialisasi. Jika klien multi-utas memanggil method1 dan method2 pada antarmuka IFoo , dan method3 pada antarmuka IBar , method1 dan method2 akan selalu diserialisasi, tetapi method3 dapat berjalan secara paralel dengan method1 dan method2 .

Satu utas eksekusi klien dapat menyebabkan eksekusi bersamaan di server dengan banyak utas dalam dua cara:

  • panggilan oneway tidak memblokir. Jika panggilan oneway dijalankan dan kemudian panggilan non- oneway , server dapat mengeksekusi panggilan oneway dan panggilan non- oneway secara bersamaan.
  • Metode server yang meneruskan data kembali dengan panggilan balik sinkron dapat membuka blokir klien segera setelah panggilan balik dipanggil dari server.

Untuk cara kedua, kode apa pun dalam fungsi server yang dijalankan setelah panggilan balik dipanggil dapat dieksekusi secara bersamaan, dengan server menangani panggilan berikutnya dari klien. Ini termasuk kode dalam fungsi server dan destruktor otomatis yang dijalankan di akhir fungsi. Jika server memiliki lebih dari satu utas di kumpulan utasnya, masalah konkurensi muncul bahkan jika panggilan masuk hanya dari satu utas klien tunggal. (Jika ada HAL yang dilayani oleh suatu proses membutuhkan banyak utas, semua HAL akan memiliki banyak utas karena kumpulan utas dibagikan per proses.)

Segera setelah server memanggil callback yang disediakan, transport dapat memanggil callback yang diimplementasikan pada klien dan membuka blokir klien. Klien melanjutkan secara paralel dengan apa pun yang dilakukan implementasi server setelah memanggil panggilan balik (yang mungkin termasuk menjalankan destruktor). Kode dalam fungsi server setelah panggilan balik tidak lagi memblokir klien (selama server threadpool memiliki cukup utas untuk menangani panggilan masuk), tetapi dapat dieksekusi secara bersamaan dengan panggilan mendatang dari klien (kecuali server threadpool hanya memiliki satu utas ).

Selain panggilan balik sinkron, panggilan oneway dari klien utas tunggal dapat ditangani secara bersamaan oleh server dengan banyak utas di kumpulan oneway , tetapi hanya jika panggilan satu arah tersebut dieksekusi pada antarmuka yang berbeda. panggilan oneway pada antarmuka yang sama selalu serial.

Catatan: Kami sangat menganjurkan fungsi server untuk kembali segera setelah mereka memanggil fungsi panggilan balik.

Misalnya (dalam 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
};

Model threading klien

Model threading pada klien berbeda antara panggilan non-pemblokiran (fungsi yang ditandai dengan kata kunci oneway ) dan panggilan pemblokiran (fungsi yang tidak memiliki kata kunci oneway yang ditentukan).

Memblokir panggilan

Untuk memblokir panggilan, klien memblokir hingga salah satu hal berikut terjadi:

  • Terjadi kesalahan transportasi; objek Return berisi status kesalahan yang dapat diambil dengan Return::isOk() .
  • Implementasi server memanggil panggilan balik (jika ada).
  • Implementasi server mengembalikan nilai (jika tidak ada parameter panggilan balik).

Jika berhasil, fungsi panggilan balik yang diteruskan klien sebagai argumen selalu dipanggil oleh server sebelum fungsi itu sendiri kembali. Panggilan balik dieksekusi pada utas yang sama dengan panggilan fungsi, jadi pelaksana harus berhati-hati dengan menahan kunci selama panggilan fungsi (dan menghindarinya sama sekali jika memungkinkan). Fungsi tanpa pernyataan generates atau kata kunci oneway masih diblokir; klien memblokir hingga server mengembalikan objek Return<void> .

Panggilan sekali jalan

Ketika suatu fungsi ditandai oneway , klien segera kembali dan tidak menunggu server menyelesaikan pemanggilan panggilan fungsinya. Di permukaan (dan secara agregat), ini berarti pemanggilan fungsi membutuhkan separuh waktu karena mengeksekusi separuh kode, tetapi ketika menulis implementasi yang sensitif terhadap kinerja, ini memiliki beberapa implikasi penjadwalan. Biasanya, menggunakan panggilan satu arah menyebabkan pemanggil terus dijadwalkan sedangkan menggunakan panggilan sinkron normal menyebabkan penjadwal segera mentransfer dari pemanggil ke proses callee. Ini adalah optimasi kinerja di binder. Untuk layanan di mana panggilan satu arah harus dijalankan dalam proses target dengan prioritas tinggi, kebijakan penjadwalan layanan penerima dapat diubah. Dalam C++, menggunakan metode libhidltransport setMinSchedulerPolicy dengan prioritas penjadwal dan kebijakan yang ditentukan dalam sched.h memastikan bahwa semua panggilan ke layanan berjalan setidaknya pada kebijakan dan prioritas penjadwalan yang ditetapkan.