I metodi contrassegnati come oneway
non vengono bloccati. Per i metodi non contrassegnati come
oneway
, la chiamata al metodo di un client si blocca finché il server non ha
completata o chiamata sincronizzazione sincrona (a seconda dell'evento che si verifica per primo).
Le implementazioni dei metodi server possono chiamare al massimo un callback sincrono; extra
le chiamate di callback vengono ignorate e registrate come errori. Se un metodo dovrebbe
restituisce valori tramite callback e non chiama il callback, questo viene registrato come
e segnalato come errore di trasporto al client.
Thread in modalità passthrough
In modalità passthrough, la maggior parte delle chiamate è sincrona. Tuttavia, per preservare il
comportamento previsto che le chiamate oneway
non bloccano il client,
viene creato un thread per ogni processo. Per maggiori dettagli, consulta
Panoramica di HIDL.
Fili negli HAL binderizzati
Per gestire le chiamate RPC in entrata (inclusi i callback asincroni dagli HAL agli utenti HAL) e notifiche di morte, a ogni processo è associato un pool di thread che utilizza l'HIDL. Se un singolo processo implementa più interfacce HIDL e/o per i gestori delle notifiche di morte, il relativo pool di thread è condiviso tra tutti. Quando Un processo riceve una chiamata di metodo in entrata da un client, sceglie un thread senza costi dal pool di thread ed esegue la chiamata su quel thread. Se non è disponibile alcun thread senza costi se è disponibile, si blocca finché non ne è disponibile uno.
Se il server ha un solo thread, le chiamate al server vengono completate
in ordine. Un server con più di un thread potrebbe completare le chiamate in modo non corretto
anche se il client ha un solo thread. Tuttavia, per un determinato oggetto dell'interfaccia,
È garantito che oneway
chiamate vengano ordinate (vedi
modello di thread del server). Per un server multi-thread che
ospita più interfacce, oneway
chiamate a interfacce diverse
potrebbero essere elaborate contemporaneamente tra loro o con altre chiamate di blocco.
Più chiamate nidificate vengono inviate nello stesso thread hwbinder. Ad esempio, se un processo (A) effettua una chiamata sincrona da un thread hwbinder al processo (B), mentre il processo (B) effettua una chiamata sincrona al processo (A), la chiamata viene eseguito sul thread hwbinder originale in (A), che è bloccato sull'originale chiamata. Questa ottimizzazione permette di avere un singolo server con thread in grado di a gestire le chiamate nidificate, ma non si estende ai casi in cui avvengono un'altra sequenza di chiamate IPC. Ad esempio, se il processo (B) avesse effettuato una a binder/vndbinder, che si inserisce in un processo (C) e poi a un processo (C) in (A), non può essere pubblicato nel thread originale in (A).
Modello di thread del server
Ad eccezione della modalità passthrough, le implementazioni del server delle interfacce HIDL sono attive in un processo diverso rispetto al client e hanno bisogno di uno o più thread in attesa chiamate al metodo in arrivo. Questi thread sono il pool di thread del server; il server può decide quanti thread vuole eseguire nel suo pool di thread e può utilizzare un una dimensione del pool di thread pari a uno per serializzare tutte le chiamate sulle relative interfacce. Se il server ha più di un thread nel pool di thread, può ricevere messaggi in entrata in su una delle sue interfacce (in C++, questo significa che i dati condivisi chiuso con attenzione).
Le chiamate unidirezionali nella stessa interfaccia sono serializzate. Se un modello multi-thread
il client chiama method1
e method2
nell'interfaccia
IFoo
e method3
nell'interfaccia IBar
,
method1
e method2
sono sempre serializzati, ma
method3
può essere eseguito in parallelo con method1
e
method2
.
Un singolo thread client di esecuzione può causare l'esecuzione simultanea su un server con più thread in due modi:
- Le chiamate
oneway
non vengono bloccate. Se una chiamataoneway
viene e poi viene chiamatooneway
, il server può eseguire la chiamataoneway
e la chiamata nononeway
contemporaneamente. - I metodi server che ritrasmettono i dati con callback sincroni possono sbloccare sul client non appena il server richiama il callback.
Il secondo modo, ogni codice nella funzione server che viene eseguito dopo il callback può essere eseguito contemporaneamente, mentre il server gestisce le dal cliente. È incluso il codice nella funzione del server e distruttivi che vengono eseguiti alla fine della funzione. Se il server ha più di un thread nel suo threadpool, sorgono problemi di contemporaneità anche se le chiamate da un solo thread client. Se un HAL gestito da un processo richiede più thread, tutti gli HAL hanno più thread perché il pool di thread condivise per processo).
Non appena il server chiama il callback fornito, il trasporto può chiamare il metodo ha implementato il callback sul client e sbloccarlo. Il cliente procede in parallelo con qualsiasi azione eseguita dall'implementazione del server dopo aver chiamato (che potrebbe includere l'esecuzione dei distruttori). Codice nella funzione server dopo che il callback non blocca più il client (purché il server threadpool dispone di un numero sufficiente di thread per gestire le chiamate in arrivo), ma potrebbe essere eseguito in concomitanza con chiamate future del client (a meno che il pool di thread del server non un solo thread).
Oltre ai callback sincroni, oneway
di chiamate da un
client a thread singolo può essere gestito contemporaneamente da un server
thread nel rispettivo pool di thread, ma solo se le chiamate a oneway
vengono
eseguite su diverse interfacce. oneway
chiamate contemporaneamente
sono sempre serializzati.
Nota: consigliamo vivamente alle funzioni server di ritornano appena hanno chiamato la funzione di callback.
Ad esempio (in 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 };
Modello di thread dei client
Il modello di organizzazione in thread sul client è diverso tra le chiamate non bloccanti
(funzioni contrassegnate con la parola chiave oneway
) e blocco
(funzioni per le quali non è specificata la parola chiave oneway
).
Blocca chiamate
Per bloccare le chiamate, il client blocca le chiamate finché non si verifica una delle seguenti situazioni:
- Si è verificato un errore di trasporto. l'oggetto
Return
contiene un errore stato recuperabile conReturn::isOk()
. - L'implementazione del server chiama il callback (se presente).
- L'implementazione del server restituisce un valore (se non esiste un parametro di callback).
In caso di esito positivo, la funzione di callback che il client passa come argomento è
sempre chiamata dal server prima che la funzione stessa restituisca. Il richiamo è
sullo stesso thread su cui viene effettuata la chiamata di funzione, quindi
occorre fare attenzione a tenere premuti i blocchi durante le chiamate di funzione (ed evitarli
completamente se possibile). Una funzione senza un'istruzione generates
oppure una parola chiave oneway
è ancora bloccata; che il client blocca finché
restituisce un oggetto Return<void>
.
Chiamate unidirezionali
Quando una funzione è contrassegnata come oneway
, il client restituisce immediatamente
e non attende che il server completi la chiamata di funzione. Al
superficie (e in forma aggregata), significa che la chiamata di funzione prende metà
molto tempo perché esegue metà del codice, ma quando scrivi le implementazioni
sono sensibili alle prestazioni, questo comporta
alcune implicazioni per la pianificazione. Generalmente,
se utilizzi una chiamata unidirezionale, il chiamante continua a essere programmato mentre
l'uso di una normale chiamata sincrona fa sì che lo scheduler trasferisca immediatamente
dal chiamante al processo della persona chiamata. Si tratta di un'ottimizzazione del rendimento
. Per i servizi in cui la chiamata unidirezionale deve essere eseguita nel processo di destinazione
con priorità elevata, i criteri di pianificazione del servizio ricevente possono essere
è cambiato. In C++, utilizzando il metodo di libhidltransport
setMinSchedulerPolicy
con priorità e norme dello scheduler
definita in sched.h
garantisce che tutte le chiamate al servizio vengano eseguite in
almeno al criterio di pianificazione e alla priorità impostati.