Linhas de execução do modelo

Métodos marcados como oneway não são bloqueados. Para métodos não marcados como oneway, a chamada do método de um cliente fica bloqueada até que o servidor concluída ou chamado de callback síncrono (o que ocorrer primeiro). As implementações de método do servidor podem chamar no máximo um callback síncrono. extras chamadas de callback são descartadas e registradas como erros. Se um método precisar retorna valores por meio de callback e não invoca o callback, isso é registrado como e relatado como um erro de transporte ao cliente.

Linhas de execução no modo de passagem

No modo de passagem, a maioria das chamadas é síncrona. No entanto, para preservar comportamento pretendido que o método oneway chama sem bloquear o cliente, uma linha de execução é criada para cada processo. Para mais detalhes, consulte a Visão geral do HIDL.

Linhas de execução em HALs vinculadas

Para atender a chamadas RPC recebidas (incluindo callbacks assíncronos de HALs para usuários da HAL) e notificações de interrupção, um grupo de linhas de execução é associado a cada processo que usa HIDL. Se um único processo implementar várias interfaces HIDL e/ou gerenciadores de notificações de morte, seu pool de linhas de execução será compartilhado entre todos eles. Quando um processo recebe uma chamada de método recebida de um cliente, ele escolhe uma linha de execução livre do pool de linhas de execução e executa a chamada nessa linha. Se nenhuma linha de execução livre for disponível, ele fica bloqueado até que um esteja disponível.

Se o servidor tiver apenas um thread, as chamadas para o servidor serão concluídas em ordem. Um servidor com mais de um thread pode concluir chamadas fora de ordem mesmo que o cliente tenha apenas um thread. No entanto, para um determinado objeto de interface, As chamadas oneway serão ordenadas corretamente. Consulte modelo de linha de execução do servidor). Para um servidor com vários segmentos que hospeda várias interfaces, oneway chamadas para interfaces diferentes podem ser processadas simultaneamente umas às outras ou com outras chamadas de bloqueio.

Várias chamadas aninhadas são enviadas na mesma linha de execução hwbinder. Por exemplo: se um processo (A) faz uma chamada síncrona de uma linha de execução hwbinder para o processo (B), e depois o processo (B) faz uma chamada síncrona de volta ao processo (A), a chamada é executada na linha de execução hwbinder original em (A), que está bloqueada na a chamada. Essa otimização possibilita ter um único servidor de linha de execução capaz de lida com chamadas aninhadas, mas não se estende a casos em que as chamadas são transmitidas outra sequência de chamadas de IPC. Por exemplo, se o processo (B) tivesse feito chamada de vinculação/vndbinder que chamou um processo (C) e depois processa as chamadas (C) de volta em (A), ele não pode ser veiculado na linha de execução original em (A).

Modelo de linha de execução do servidor

Exceto para o modo de passagem, as implementações do servidor de interfaces HIDL estão ativas em um processo diferente daquele do cliente e precisam de uma ou mais linhas de execução esperando chamadas de método recebidas. Elas são o pool de linhas de execução do servidor. o servidor pode decide quantas linhas de execução quer executar no pool de linhas de execução e pode usar uma tamanho do pool de linhas de execução de um para serializar todas as chamadas nas interfaces. Se o servidor tiver mais de uma linha de execução no pool, ele poderá receber entradas simultâneas em qualquer uma de suas interfaces (em C++, isso significa que os dados compartilhados devem ser cuidadosamente).

As chamadas unidirecionais na mesma interface são serializadas. Se um cliente com várias linhas de execução o cliente chama method1 e method2 na interface IFoo e method3 na interface IBar method1 e method2 são sempre serializados, mas method3 pode ser executado em paralelo com method1 e method2.

Um único thread do cliente pode causar uma execução simultânea em um com vários segmentos de duas maneiras:

  • As chamadas oneway não são bloqueadas. Se uma chamada oneway for executado e um não oneway for chamado, o servidor poderá as chamadas oneway e as que não são oneway ao mesmo tempo.
  • Os métodos de servidor que transmitem dados de volta com callbacks síncronos podem ser desbloqueados o cliente assim que a chamada de retorno for feita pelo servidor.

A segunda maneira, qualquer código na função do servidor que seja executado após a é chamado pode ser executado simultaneamente, com o servidor lidando com as do cliente. Isso inclui código na função de servidor e destruidores que são executados no final da função. Se o servidor tiver mais de uma linha de execução no pool de linhas de execução, surgem problemas de simultaneidade mesmo quando as chamadas estão em apenas uma conversa do cliente. Se alguma HAL veiculada por um processo precisar várias linhas de execução, todas as HALs têm várias linhas de execução, pois o conjunto de compartilhados por processo.

Assim que o servidor chamar o retorno de chamada fornecido, o transporte poderá chamar o método implementar o callback no cliente e desbloqueá-lo. O cliente prossegue em paralelo com o que a implementação do servidor fizer depois de chamar o método o que pode incluir a execução de destruidores. Código na função de servidor após o retorno de chamada não estar mais bloqueando o cliente (contanto que o servidor o pool de linhas de execução tem linhas de execução suficientes para processar chamadas recebidas), mas pode ser executado simultaneamente com futuras chamadas do cliente (a menos que o pool de linhas de execução do servidor tenha apenas um thread).

Além dos callbacks síncronos, oneway chama de um um cliente de thread único pode ser manipulado simultaneamente por um servidor com vários linhas de execução no pool, mas somente se essas chamadas oneway forem executados em diferentes interfaces. oneway chamadas ao mesmo são sempre serializadas.

Observação: recomendamos que as funções de servidor retornar assim que chamarem a função de callback.

Por exemplo (em 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
};

Modelo de linha de execução do cliente

O modelo de linha de execução no cliente é diferente entre chamadas sem bloqueio (funções marcadas com a palavra-chave oneway) e bloqueio chamadas (funções que não têm a palavra-chave oneway especificada).

Bloquear chamadas

Para o bloqueio de chamadas, o cliente bloqueia até que uma das seguintes situações aconteça:

  • Ocorre um erro de transporte. o objeto Return contém um erro que pode ser recuperado com Return::isOk().
  • A implementação do servidor chama o callback (se houver).
  • A implementação do servidor retorna um valor (se não houver um parâmetro de callback).

Em caso de sucesso, a função de retorno de chamada que o cliente passa como um argumento é sempre chamado pelo servidor antes do retorno da própria função. O callback é executada na mesma linha de execução em que a chamada de função é feita. Assim, os implementadores deve ter cuidado ao manter bloqueios durante chamadas de função (e evitá-los completamente, quando possível). Uma função sem uma instrução generates ou se uma palavra-chave oneway ainda estiver bloqueando, que o cliente bloqueia até que "server" retorna um objeto Return<void>.

Chamadas unidirecionais

Quando uma função é marcada como oneway, o cliente retorna imediatamente. e não espera o servidor concluir a invocação da chamada de função. No (e agregados), isso significa que a chamada da função ocupa metade da tempo porque está executando metade do código, mas ao escrever implementações que são sensíveis ao desempenho, isso tem algumas implicações na programação. Normalmente, o uso de uma chamada unidirecional faz com que o autor da chamada continue a ser agendado, enquanto o uso de uma chamada síncrona normal faz com que o programador transfira imediatamente do autor da chamada para o processo do recebedor da chamada. Essa é uma otimização de desempenho fichário. Para serviços em que a chamada unidirecional precisa ser executada no processo de destino com alta prioridade, a política de agendamento do serviço receptor pode ser alterado. Em C++, usando o método de libhidltransport. setMinSchedulerPolicy com as prioridades e políticas do programador definido em sched.h garante que todas as chamadas para o serviço sejam executadas pelo menos com a política e a prioridade definidas.