스레딩 모델

oneway로 표시된 메서드는 블록하지 않습니다. oneway로 표시된 메서드의 경우 클라이언트의 메서드 호출은 서버에서 실행을 완료하거나 동기식 콜백(먼저 발생하는 것 우선)을 호출할 때까지 블록합니다. 서버 메서드 구현 시 동기식 콜백이 최대 1회 호출될 수 있습니다. 추가 콜백 호출은 삭제되거나 오류로 로그됩니다. 메서드가 콜백을 통해 값을 반환하고 콜백을 호출하지 않는 경우 오류로 로그되며 클라이언트에 전송 오류로 보고됩니다.

패스 스루 모드의 스레드

패스 스루 모드에서 대부분의 호출은 동기식입니다. 하지만 oneway 호출에서 클라이언트를 차단하지 않는 정상적인 상태를 유지하기 위해 프로세스마다 스레드가 생성됩니다. 자세한 내용은 HIDL 개요를 참고하세요.

바인더화된 HAL의 스레드

HAL에서 HAL 사용자에게 전달되는 비동기식 콜백 등 수신 RPC 호출 및 종료 알림을 제공하기 위해 HIDL을 사용하는 각각의 프로세스에 스레드 풀이 연결됩니다. 단일 프로세스가 다수의 HIDL 인터페이스 및 종료 알림 핸들러를 구현하는 경우 스레드 풀은 이들 모두 간에 공유됩니다. 프로세스가 클라이언트로부터 수신 메서드 호출을 받으면, 프로세스는 해제된 스레드를 스레드 풀에서 선택하여 해당 스레드에서 호출을 실행합니다. 사용할 수 있는 해제된 스레드가 없는 경우, 사용 가능할 때까지 차단이 발생합니다.

서버에 스레드가 하나만 있으면 서버로 전달되는 호출이 순서대로 완료됩니다. 클라이언트가 스레드를 하나만 갖고 있더라도 스레드가 두 개 이상인 서버에서 비순차적으로 호출을 완료할 수 있습니다. 하지만 지정된 인터페이스 객체의 경우 oneway 호출은 순서대로 완료됩니다(서버 스레딩 모델 참고). 여러 인터페이스를 호스팅하는 다중 스레드 서버의 경우, 각기 다른 인터페이스로 전달되는 oneway 호출은 서로 간에 또는 다른 블로킹 호출과 동시에 처리될 수 있습니다.

여러 개의 중첩 호출은 동일한 hwbinder 스레드에서 전송됩니다. 예를 들어, 프로세스 (A)가 hwbinder 스레드에서 프로세스 (B)로 동기적 호출을 발생시킨 뒤 프로세스 (B)가 프로세스 (A)로 동기적 호출을 다시 발생시키면 최초 호출에서 차단된 (A)의 최초 hwbinder 스레드에서 호출이 실행됩니다. 이 최적화를 통해 단일 스레드 서버에서 중첩 호출을 처리할 수 있지만 IPC 호출의 다른 시퀀스를 통해 호출이 이동하는 경우로 확장되지는 않습니다. 예를 들어, 프로세스 (B)가 프로세스 (C)로 호출한 binder/vndbinder 호출을 발생시킨 뒤 프로세스 (C)가 (A)로 다시 호출한 경우 binder/vndbinder 호출은 (A)의 원래 스레드에서 제공될 수 없습니다.

서버 스레딩 모델

패스 스루 모드를 제외하고 HIDL 인터페이스의 서버 구현은 클라이언트와 다른 프로세스에서 진행되며 수신 메서드 호출을 기다리는 하나 이상의 스레드가 필요합니다. 이러한 스레드는 서버의 스레드 풀입니다. 서버는 스레드 풀에서 실행하고자 하는 스레드의 수를 결정할 수 있으며 스레드 풀 크기를 1로 사용하여 인터페이스의 모든 호출을 직렬화할 수 있습니다. 서버가 스레드 풀에서 스레드를 두 개 이상 보유하는 경우 인터페이스에서 동시 수신 호출을 받을 수 있습니다. 따라서 C++에서 공유 데이터를 잠글 때 신중해야 합니다.

동일한 인터페이스로 전달되는 일방향 호출은 직렬화됩니다. 다중 스레드 클라이언트가 인터페이스 IFoomethod1method2, 인터페이스 IBarmethod3을 호출하는 경우 method1method2는 항상 직렬화되나 method3method1method2와 병렬로 실행될 수 있습니다.

다음 두 가지 방법으로 단일 클라이언트 실행 스레드에 의해 여러 스레드가 있는 서버에서 동시 실행이 발생할 수 있습니다.

  • oneway 호출은 차단하지 않습니다. oneway 호출이 실행된 후에 비oneway가 호출된 경우 서버는 oneway 호출 및 비oneway 호출을 동시에 실행할 수 있습니다.
  • 동기적 콜백을 사용하여 데이터를 다시 전달하는 서버 메서드는 콜백이 서버에서 호출되는 즉시 클라이언트를 차단 해제할 수 있습니다.

두 번째 방법에서는 콜백이 호출된 후 실행되는 서버 함수의 코드가 동시 실행될 수 있으며 이때 서버는 클라이언트의 후속 호출을 처리할 수 있습니다. 여기에는 서버 함수의 코드와 함수의 끝에서 실행하는 자동 소멸자가 포함됩니다. 서버가 스레드 풀에서 스레드를 두 개 이상 보유하는 경우 단일 클라이언트 스레드 한 곳으로부터만 호출이 전달된다 하더라도 동시 실행 문제가 발생합니다. 프로세스에서 제공하는 HAL에 여러 스레드가 필요한 경우 스레드 풀이 프로세스별로 공유되므로 모든 HAL에서 여러 스레드를 갖게 됩니다.

서버가 제공된 콜백을 호출하는 즉시, 전송은 클라이언트에서 구현된 콜백을 호출하고 클라이언트를 차단 해제할 수 있습니다. 클라이언트는 소멸자 실행을 포함할 수도 있는 콜백을 호출한 후 서버 구현이 실행하는 작업과 동시에 진행됩니다. 서버 스레드 풀에 수신 호출을 처리할 스레드가 충분히 있는 한, 콜백 이후에 서버 함수의 코드는 클라이언트를 더 이상 차단하지 않게 됩니다. 하지만 서버 함수의 코드는 클라이언트에서 전달되는 이후의 호출과 동시에 실행될 가능성이 있습니다(서버 스레드 풀에 스레드가 하나밖에 없는 경우 제외).

동기적 콜백 외에도 단일 스레드 클라이언트에서 전달되는 oneway 호출은 스레드 풀에 여러 스레드가 있는 서버에서 동시에 처리될 수 있습니다. 단, oneway 호출이 각기 다른 인터페이스에서 실행되는 경우에 한합니다. 동일한 인터페이스의 oneway 호출은 항상 직렬화됩니다.

참고: 서버 함수는 콜백 함수를 호출하는 즉시 반환하는 것이 좋습니다.

예를 들면 다음과 같습니다(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
};

클라이언트 스레딩 모델

클라이언트의 스레딩 모델은 oneway 키워드로 표시된 함수인 비차단 호출과 oneway 키워드를 지정하지 않은 함수인 차단 호출 간에 차이를 보입니다.

차단 호출

차단 호출의 경우 클라이언트는 다음 중 하나가 발생할 때까지 차단합니다.

  • 전송 오류가 발생했습니다. Return 객체에 Return::isOk()로 검색될 수 있는 오류 상태가 있습니다.
  • 서버 구현이 콜백을 호출합니다(콜백이 있는 경우).
  • 서버 구현이 값을 반환합니다(콜백 매개변수가 없는 경우).

성공할 경우 클라이언트가 인수로서 전달하는 콜백 함수는 함수 자체가 반환되기 전에 항상 서버에 의해 호출됩니다. 콜백은 함수 호출이 생성되는 스레드와 동일한 스레드에서 실행되므로 구현자는 함수 호출 중 잠금 유지에 유의해야 합니다(가능하면 전부 피하기). generates 문 또는 oneway 키워드가 없는 함수는 계속해서 차단하며 클라이언트는 서버가 Return<void> 객체를 반환할 때까지 차단합니다.

일방향 호출

함수가 oneway로 표시되는 경우 클라이언트는 즉시 반환하고 서버가 함수 호출을 완료할 때까지 대기하지 않습니다. 표면적으로나 총체적으로 봤을 때 이는 함수 호출이 코드의 절반을 실행하기 때문에 시간도 절반만 소요됨을 의미하지만, 성능과 직결되는 구현을 작성하는 경우 일정과 관련한 영향이 발생할 수 있습니다. 일방향 호출을 사용하면 대개 호출자가 예약 상태를 유지하지만, 일반 동기식 호출을 사용하면 스케줄러가 즉시 호출자에서 피호출자 프로세스로 이동합니다. 이는 바인더에서의 성능 최적화입니다. 우선 순위가 높은 대상 프로세스에서 일방향 호출을 실행해야 하는 서비스의 경우, 수신 서비스의 일정 정책을 변경할 수 있습니다. C++의 경우, 스케줄러 우선순위와 정책이 sched.h에 정의된 libhidltransport의 메서드 setMinSchedulerPolicy는 서비스로 전달되는 모든 호출이 최소한 설정된 일정 정책 및 우선순위에 맞게 실행되도록 합니다.