스트랜드: 명시적 잠금 없이 스레드 사용 (Strands: Use Threads Without Explicit Locking)
스트랜드(strand)는 이벤트 핸들러의 엄격한 순차 호출(즉, 동시 호출 없음)로 정의된다. 스트랜드(strands)를 사용하면 멀티스레드 프로그램에서 명시적 잠금(예:뮤텍스 사용)없이 코드를 실행할 수 있다.
스트랜드(strands)는 다음 선택 가능한 방식에서 설명하는 것처럼 암시적이나 명시적일 수 있다:
- 하나의 스레드에서만 io_context::run()을 호출하면 모든 이벤트 핸들러가 암시적으로 스트랜드(strand)에서 실행되는 것을 의미한다. 핸들러가 run() 내부에서만 호출된다는 io_context의 보장 때문이다.
- 연결과 관련된 비동기식 작업용 단일 체인이 있는 경우(예: HTTP와 같은 반이중 프로토콜 구현) 핸들러의 동시 실행 가능성은 없다. 이것은 암시적인 스트랜드(strand)이다.
- 명시적 스트랜드(strand)는 strand<> 또는 io_context::strand의 인스턴스이다. 모든 이벤트 핸들러 함수 개체는 boost::asio::bind_executor()를 사용하여 스트랜드(strand)에 바인드하거나 스트랜드(strand) 개체를 통해 게시/처리(posted/dispatched) 해야 한다.
async_read()나 async_read_until()과 같은 비동기식 작업 구성의 경우, 완료 핸들러가 스트랜드(strand)를 통과하면 모든 중간 핸들러도 동일한 스트랜드(strand)를 통과해야 한다. 이것은 호출자와 구성된 작업 사이에 공유되는 모든 개체에 대해 스레드 안전 접근을 보장하기 위해 필요하다(async_read()의 경우 호출자가 작업을 취소하기 위해 close() 할 수 있는 소켓).
이를 위해 모든 비동기식 작업은 get_associated_executor 함수를 사용하여 핸들러와 연결된 실행기(executor)를 가져온다. 예를 들면:
boost::asio::associated_executor_t<Handler> a = boost::asio::get_associated_executor(h);
연결된 실행기(executor)는 실행기의 요구 사항을 만족해야 한다. 이는 비동기식 작업에서 실행을 위해 중간 및 최종 핸들러를 제출하는 데 사용된다.
실행기(executor)는 중첩 유형인 executor_type 및 멤버 함수 get_executor()를 지정하여 특정 핸들러 유형으로 사용자 정의할 수 있다:
class my_handler { public: // Custom implementation of Executor type requirements. typedef my_executor executor_type; // Return a custom executor implementation. executor_type get_executor() const noexcept { return my_executor(); } void operator()() { ... } };
더 복잡한 경우, associated_executor 템플릿은 직접 부분적으로 특수화할 수 있다:
struct my_handler { void operator()() { ... } }; namespace boost { namespace asio { template <class Executor> struct associated_executor<my_handler, Executor> { // Custom implementation of Executor type requirements. typedef my_executor type; // Return a custom executor implementation. static type get(const my_handler&, const Executor& = Executor()) noexcept { return my_executor(); } }; } } // namespace boost::asio
boost::asio::bind_executor() 함수는 스트랜드(strand)와 같은 특정 실행기(executor) 개체를 완료 핸들러에 바인딩하는 도우미다. 이 바인딩은 위와 같이 실행기(executor)를 자동으로 연결한다. 예를 들어, 스트랜드(strand)를 완료 핸들러에 바인딩하려면 다음과 같이 간단히 작성한다:
my_socket.async_read_some(my_buffer, boost::asio::bind_executor(my_strand, [](error_code ec, size_t length) { // ... }));
더 보기
associated_executor, get_associated_executor, bind_executor, strand, io_context::strand, tutorial Timer.5, HTTP server 3 example.
'Boost C++ Libraries > Boost.Asio' 카테고리의 다른 글
Boost.Asio 개요 - 핵심 개념 및 기능 - 스트림, 짧은 읽기와 짧은 쓰기 (0) | 2020.12.08 |
---|---|
Boost.Asio 개요 - 핵심 개념 및 기능 - 버퍼 (0) | 2020.12.07 |
Boost.Asio 개요 - 핵심 개념 및 기능 - 스레드와 Boost.Asio (0) | 2020.12.07 |
Boost.Asio 개요 - 핵심 개념 및 기능 - Proactor 디자인 패턴: 스레드 없는 동시 실행 (0) | 2020.12.06 |
Boost.Asio 개요 - 핵심 개념 및 기능 - Boost.Asio 기본 구조 (0) | 2020.12.05 |