Threading del modello

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 chiamata oneway viene e poi viene chiamato oneway, il server può eseguire la chiamata oneway e la chiamata non oneway 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 con Return::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.