Boost.Fiber Customization


Customization

📦 Overview - 개요

스케줄링 섹션에서 언급했듯이, 기본적으로 Boost.Fiber는 각 스레드에 대해 자체 round_robin 스케줄러를 사용합니다.   Boost.Fiber가 특정 스레드에서 준비된 파이버를 예약하는 방식을 제어하려면 일반적으로 몇 가지 단계를 수행해야 합니다.   이 섹션에서는 해당 단계에 대해 설명하는 반면, 예약(Scheduling)은 관련 클래스에 대한 참조 역할을 합니다.

라이브러리의 파이버 관리자는 중단된(차단된) 파이버을 추적합니다.   파이버가 실행 준비가 된 경우에만 스케줄러로 전달됩니다.   물론, 준비된 파이버가 2개 미만인 경우 스케줄러의 작업은 사소합니다.   두 개 이상의 준비된 파이버가 있는 경우에만 특정 스케줄러 구현이 파이버 실행의 전체 순서에 영향을 미치기 시작합니다.

이 섹션에서는 정수(integer) 파이버 우선순위를 존중하는 간단한 사용자 정의 스케줄러를 설명합니다.   우리는 우선순위가 낮은 파이버보다 우선순위가 높은 파이버가 우선되도록 구현할 것입니다.   우선순위 값이 동일한 모든 파이버는 라운드 로빈(round-robin) 방식으로 서비스됩니다.

아래 예제의 전체 소스 코드는 priority.cpp에 있습니다.
https://www.boost.org/doc/libs/1_85_0/libs/fiber/examples/priority.cpp

📦 Custom Property Class

첫 번째 필수 사항은 각 파이버에 정수 우선 순위를 연결해야 한다는 것입니다.[11]

그러한 속성을 저장하기 위해 사용자 정의 파이버 하위 클래스를 파생시키는 것이 제안될 수도 있습니다.
현재 메커니즘에는 몇 가지 이유가 있습니다.

  1. Boost.Fiber는 파이버를 시작하는 다양한 방법을 제공합니다.   (fibers::async()를 고려하십시오) 상위 수준 라이브러리에서는 이러한 래퍼 기능을 추가로 도입할 수 있습니다.   사용자 정의 스케줄러는 사용자 정의 파이버 하위 클래스를 인스턴스화하여 명시적으로 시작된 파이버뿐만 아니라 스레드의 모든 파이버와 사용자 정의 속성을 연결해야 합니다.
  2. 코드의 다양한 위치에서 파이버를 실행하는 대규모 기존 프로그램을 생각해 보세요.   우리는 특정 스레드에 대한 사용자 정의 스케줄러를 도입해야 할 필요성을 발견했습니다.   해당 스케줄러의 사용자 정의 속성을 지원하는 데 특정 파이버 하위 클래스가 필요한 경우 해당 스레드에서 파이버를 실행하는 모든 위치를 찾아 수정해야 합니다.
  3. 파이버 클래스는 실제로 내부 컨텍스트 데이터에 대한 핸들일 뿐입니다.   파이버 하위 클래스는 컨텍스트에 데이터를 추가하지 않습니다.

현재 메커니즘을 사용하면 애플리케이션의 나머지 부분을 변경하지 않고도 그에 수반되는 사용자 정의 속성이 있는 사용자 정의 스케줄러를 "drop in"할 수 있습니다.
파이버에서 사용자 정의 스케줄러 파이버 속성 하위 클래스를 파생하는 대신 'fiber_properties'에서 파생해야 합니다.

  • (1) 서브클래스 생성자는 context*를 승인하고 이를 fiber_properties 생성자에 전달해야 합니다.
  • (2) 귀하의 재량(discretion)에 따라 읽기 액세스 메서드을 제공하십시오.
  • (3) 스케줄러의 동작에 영향을 미칠 수 있는 속성의 변경 사항에 대해 notify()을 호출하는 것이 중요합니다. 따라서 이러한 수정은 액세스 메서드을 통해서만 수행되어야 합니다.
  • (4) 스케줄러에 영향을 주지 않는 속성은 액세스 메서드가 필요하지 않습니다.

[11] 이전 버전의 Fiber 라이브러리는 기본 스케줄러가 이를 무시하더라도 각 파이버의 int 우선순위를 암시적으로 추적했습니다. 이제 라이브러리가 임의의 스케줄러별(scheduler-specific) 파이버 속성을 지원하므로 이는 삭제되었습니다.

📦 Custom Scheduler Class

이제 우리는 사용자 정의 속성 클래스인 'priority_props'를 템플릿 매개변수로 지정하여 algorithm_with_properties<>에서 사용자 정의 스케줄러를 파생시킬 수 있습니다.

  • (1) 'ready_queue_t'를 참조하세요.
  • (2) algorithm_with_properties::awakened() 메서드를 재정의해야 합니다.   이는 스케줄러가 실행할 준비가 된 파이버에 대한 알림을 받는 방법입니다.
  • (3) 'props'는 전달된 파이버 'ctx'와 관련된 'priority_props'의 인스턴스입니다.
  • (4) algorithm_with_properties::pick_next() 메서드를 재정의해야 합니다.   이는 스케줄러가 실제로 실행할 다음 파이버의 파이버 관리자에게 조언하는 방법입니다.
  • (5) 파이버 관리자에게 준비 대기열의 상태를 알리려면 algorithm_with_properties::has_ready_fibers()를 재정의해야 합니다.
  • (6) algorithm_with_properties::property_change()를 재정의하는 것은 선택 사항입니다.   이 재정의는 실행 중인 파이버가 다른 준비된 파이버, 즉 이미 대기열에 있는 파이버의 우선순위를 변경하는 경우를 처리합니다.   이 경우 업데이트된 파이버를 대기열 내에서 이동하십시오.
  • (7) property_change() 재정의는 전달된 'ctx'가 준비 대기열에 없는 경우를 처리할 수 있어야 합니다.   실행 중이거나 차단되었을 수 있습니다.

우리의 예제 'priority_scheduler'는 'algorithm_with_properties::new_properties()'를 재정의하지 않습니다.
우리는 힙에 priority_props 인스턴스를 할당하는 것에 만족합니다.

📦 Replace Default Scheduler - 기본 스케줄러 교체

Boost.Fiber가 자체 기본 round_robin 대신 사용자 정의 스케줄러를 사용하도록 하려면 각 스레드 시작 시 use_scheduling_algorithm()을 호출해야 합니다.   특히 해당 스레드에서 다른 Boost.Fiber 작업을 수행하기 전에 use_scheduling_algorithm()을 호출해야 합니다.

📦 Use Properties - 속성 사용

실행 중인 파이버는 this_fiber::properties()를 호출하여 자체 fiber_properties 하위 클래스 인스턴스에 액세스할 수 있습니다.   properties<>()는 nullary 함수이지만 fiber_properties 하위 클래스를 템플릿 매개 변수로 전달해야 합니다. 파이버 인스턴스가 실행 중인 파이버와 계속 연결되어 있는 경우(즉, fiber::detach()가 아님) fiber::properties()를 사용하여 해당 파이버의 속성에 액세스할 수 있습니다.   boost::this_fiber::properties<>()와 마찬가지로, fiber_properties 하위 클래스를 템플릿 매개변수로 전달해야 합니다. 새로운 파이버 스케줄을 시작하면 파이버가 준비된 상태가 되지만 파이버 기능(fiber-function)에 즉시 들어가지는 않습니다.   현재 파이버는 다른 이유로 인해 차단(또는 양보(yields) 또는 종료(terminates))될 때까지 제어를 유지합니다.   위의 launch() 함수에서 볼 수 있듯이 파이버를 실행하고 관련 속성(예: 우선순위 등)을 즉시 설정하는 것이 합리적입니다.   그러면 사용자 정의 스케줄러는 다음에 파이버 관리자가 algorithm_with_properties::pick_next()를 호출할 때 이 정보를 활용할 수 있습니다.

⚛ 원문
Email 답글이 올라오면 이메일로 알려드리겠습니다.