Executor requirements (실행기 요구 사항)
표준 실행기 (Standard executors)
executor-of-impl을 기술(설명)-전용 개념으로 둔다.
template<class E, class F> concept executor-of-impl = invocable<decay_t<F>&> && constructible_from<decay_t<F>, F> && move_constructible<decay_t<F>> && copy_constructible<E> && is_nothrow_copy_constructible_v<E> && equality_comparable<E> /* nothrow */ && requires(const E& e, F&& f) { execution::execute(e, (F&&)f); };
그런 다음 executor와 executor_of 개념은 다음과 같이 정의된다:
template<class E> concept executor = executor-of-impl<E, execution::invocable_archetype>; template<class E, class F> concept executor_of = executor<E> && executor-of-impl<E, F>;
실행기(executor)의 동등 비교나 swap 작업은 예외를 통해 종료되지 않아야 한다.
실행기(executor) 유형의 복사 생성자, 소멸자, 동등 비교, swap 함수, execute 함수나 관련 query 함수는 서로 다른 스레드에서 해당 함수의 동시 호출의 결과로 데이터 경합을 발생시키지 않는다.
일부 실행기(executor) 유형 X의 두 값 (아마도 const) x1과 x2에 대해, boost::asio::query(x1, p)와 boost::asio::query(x2, p) 모두 올바른 형식이고 결과가 void 유형이 아닌 equality_compatable(C++Std [equalitycomparable])와 같은 모든 속성 p에 대해 boost::asio::query(x1, p) == boost::asio::query(x2, p)이면, x1 == x2는 true를 반환해야 한다. [참고 : x1과 x2가 동일한 효과로 교환될 수 있으면, 위의 요구 사항 x1 == x2가 true를 반환한다는 것을 의미한다. 실행기(executor)는 boost::asio::query를 통해 관찰될 수 있는 명명된 속성 유형에 의해 노출되지 않는 추가 속성을 개념적으로 포함할 수 있다. 이 경우, 이러한 속성이 동등성에 영향을 미치는지 여부를 결정하는 것은 구체적인 실행기(executor) 구현에 달려 있다. false를 반환한다고 해서 반드시 효과가 동일하지 않다는 의미는 아니다.]
실행기(executor) 유형의 소멸자는 제출된 함수 개체의 완료 보류를 차단해서는 안된다. [참고 : 제출된 함수 개체의 완료를 기다리는 기능은 연결된 실행 컨텍스트에서 제공될 수 있다.]
위의 요구사항 외에도 아래 표의 요구사항을 충족하는 경우에만, 유형 E와 F로 executor_of를 만든다.
다음을 허용한다:
- e는 유형 E의 (아마도 const) 실행기 개체를 나타내고,
- cf는 함수 개체 DECAY_COPY(std::forward<F>(f))를 나타내고
- f는 cf()로 호출할 수 있는 유형 F&&의 함수를 나타내며 여기서 decay_t로 move_constructible를 만든다.
표현식 execution::execute(e, f) :
- 호출 스레드에서 DECAY_COPY(std::forward<F>(f))를 평가하여 실행 에이전트에서 최대 한 번 호출할 수 있는 cf를 생성한다.
- 이 호출의 보류중인 완료를 차단할 수 있다. f의 호출을 [intro.multithread]와 동기화한다.
- 함수 개체나 실행기(executor)에게 제출된 다른 함수에 의해 발생한 예외를 전파해서는 안 된다.
[참고 : 단방향으로 제출된 함수에 의해 전달된 예외의 처리는 구현-정의된다. 연관된 실행 에이전트의 진행 보장은 구현-정의된다.]
네트워킹 TS-스타일 실행기 (Networking TS-style executors)
라이브러리는 실행기(executor)에 대한 표준 요구사항 집합을 설명한다. Executor(실행기) 요구사항을 충족하는 유형은 제출된 함수 개체가 실행되는 방식을 결정하기 위한 일련의 규칙을 구현한다.
CopyConstructible (C++Std [copyconstructible])와 Destructible (C++Std [destructible])의 요구사항과 아래 나열된 추가 요구사항을 충족한다면, 유형 X는 Executor(실행기) 요구사항을 충족하게 된다.
생성자, 비교 연산자, 복사 작업, 이동 작업, 스왑 작업 또는 멤버 함수 context, on_work_started와 on_work_finished는 예외를 통해 종료되지 않아야 한다.
executor(실행기) 복사 생성자, 비교 연산자와 이런 요구 사항이 정의된 다른 멤버 함수는 서로 다른 스레드에서 해당 함수에 대한 동시 호출의 결과로 데이터 경합을 도입해서는 안된다.
ctx를 실행기(executor)의 context() 멤버 함수에서 반환된 실행 컨텍스트라고 한다. ctx.shutdown()에 대한 첫 번재 호출이 반환되는 시점에 실행기(executor)는 유효하지 않게 된다. on_work_started, on_work_finished, dispatch나 defer를 유효하지 않은 실행기(executor)에서 호출하는 효과는 정의되지 않았다. [참고 : 복사 생성자, 비교 연산자와 context() 멤버 함수는 ctx가 소멸될 때까지 계속 유효하다.]
아래 표에서 x1와 x2는 유형 X의 value(가능하면 const)을 나타내고, mx1은 유형 X의 xvalue를 나타내고, f는 인수가 없는 MoveConstructible(C++Std [moveconstructible]) 함수 개체를 나타내고, a는 Allocator(할당기) 요구사항(C++Std [allocator.requirements])을 만족하는 유형 A의 value a(가능하면 const)를 나타내고, u는 식별자를 나타낸다.
표 15. Executor(실행기) 요구사항
표현식 | 유형 | assertion/note (에러 검출/참고) pre/post-condition (사전/사후 조건) |
X u(x1); | 예외를 통해 종료되지 않는다. post(사후): u == x1 그리고 std::addressof(u.context()) == std::addressof(x1.context()). |
|
X u(mx1) | 예외를 통해 종료되지 않는다. post(사후): u는 mx1 이전 값과 같고 std::addressof(u.context())는 std::addressof(mx1.context())의 이전 값과 같다. |
|
x1 == x2 | bool | x1 및 x2가 이러한 유형의 요구사항이 정의된 표현식에서 동일한 효과로 교환될 수 있으면, true를 반환한다. [참고 : false를 반환한다고 해서 반드시 효과가 동일하지 않다는 의미는 아니다.] operator==는 반사, 대칭, 전이성이어야 하고 예외를 통해 종료되지 않아야 한다. |
x1 != x2 | bool | !(x1 == x2)와 동일하다. |
x1.context() | execution_context&나 E&, E는 ExecutionContext 요구사항을 충족하는 유형이다. | 예외를 통해 종료되지 않는다. 이 요구사항에 정의된 비교 연산자와 멤버 함수는 이 함수가 반환하는 참조를 변경해서는 안된다. |
x1.on_work_started() | 예외를 통해 종료되지 않는다. | |
x1.on_work_finished() | 예외를 통해 종료되지 않는다. Precondition(사전조건): x1 == x2인 선행하는 호출 x2.on_work_started(). |
|
x1.dispatch(std::move(f), a) | 효과: 현재 실행 스레드에서 DECAY_COPY(forward<Func>(f))(C++Std [thread.decaycopy])로 초기화된 f1 개체를 생성한다. f1()을 한번만 호출한다. 실행기(executor)는 f1()이 실행을 마칠 때까지 호출자의 전방 진행을 차단할 수 있다. 실행기(executor) 구현은 제공된 할당기(allocator)를 사용하여 함수 개체를 저장하는 데 필요한 메모리를 할당해야 한다. 함수 개체를 호출하기 전에, 실행기(executor)는 할당된 메모리를 해제해야 한다. [참고 : 이 기술 사양에 정의된 Excutors(실행기)는 달리 지정되지 않으면 항상 제공된 할당기(allocator)를 사용한다.] 동기화: dispatch 호출은 f1 호출과 동기화(C++Std [intro.multithread])된다. |
|
x1.post(std::move(f), a) x1.defer(std::move(f), a) |
효과: 현재 실행 스레드에서 DECAY_COPY(forward<Func>(f))(C++Std [thread.decaycopy])로 초기화된 f1 개체를 생성한다. f1()을 한번만 호출한다. 실행기(executor)는 f1()의 완료를 대기하는 동안 호출자의 전방 진행을 차단할 수 없다. 실행기(executor) 구현은 제공된 할당기(allocator)를 사용하여 함수 개체를 저장하는 데 필요한 메모리를 할당해야 한다. 함수 개체를 호출하기 전에, 실행기(executor)는 할당된 메모리를 해제해야 한다. [참고 : 이 기술 사양에 정의된 Excutors(실행기)는 달리 지정되지 않으면 항상 제공된 할당기(allocator)를 사용한다.] 동기화: post나 defer 호출은 f1 호출과 동기화(C++Std [intro.multithread])된다. [참고 : defer에 대한 요구사항은 post와 동일하지만, post를 사용하면 호출자가 f1 진행의 첫 단계를 차단하지 않는다는 선택을 전달하는 반면, defer는 호출자가 f1의 첫 단계를 차단한다는 선택을 전달한다. defer의 한 가지 용도는 f1이 현재 호출 컨텍스트의 연속이라는 호출자의 의도를 전달하는 것이다. 실행기(executor)는 이 정보를 사용하여 f1이 호출되는 방식을 최적화하거나 조정한다.] |
'Boost C++ Libraries > Boost.Asio' 카테고리의 다른 글
Boost.Asio - ip::tcp (0) | 2021.03.25 |
---|---|
Boost.Asio - Execution context requirements (0) | 2021.03.24 |
Boost.Asio - awaitable (0) | 2021.03.23 |
Boost.Asio - Handlers (0) | 2021.03.23 |
Boost.Asio - Completion handler requirements (0) | 2021.03.22 |