Потоковые модели

Методы, помеченные как 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 будут иметь несколько потоков, поскольку пул потоков является общим для каждого процесса.)

Как только сервер вызывает предоставленный обратный вызов, транспорт может вызвать реализованный обратный вызов на клиенте и разблокировать клиента. Клиент продолжает работу параллельно с тем, что делает реализация сервера после вызова обратного вызова (который может включать запуск деструкторов). Код в серверной функции после обратного вызова больше не блокирует клиента (пока в пуле потоков сервера достаточно потоков для обработки входящих вызовов), но может выполняться одновременно с будущими вызовами от клиента (если только пул потоков сервера не имеет только одного потока). ).

В дополнение к синхронным обратным вызовам, oneway вызовы от однопоточного клиента могут обрабатываться одновременно сервером с несколькими потоками в его пуле потоков, но только если эти oneway вызовы выполняются на разных интерфейсах. oneway вызовы на одном и том же интерфейсе всегда сериализуются.

Примечание. Мы настоятельно рекомендуем серверным функциям выполнять возврат сразу же после вызова функции обратного вызова.

Например (в С++):

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++ использование метода libhidltransport setMinSchedulerPolicy с приоритетами и политиками планировщика, определенными в sched.h , гарантирует, что все вызовы службы выполняются, по крайней мере, с заданной политикой планирования и приоритетом.