동기(Synchronous) 대기 모델과 WaitSet의 구조

동기(Synchronous) 대기 모델과 WaitSet의 구조

데이터 분산 서비스(DDS, Data Distribution Service) 미들웨어는 물리적으로 분산된 노드 간의 비동기적 데이터 교환을 전제로 한다. 네트워크를 통해 데이터가 언제 도착할지, 시스템의 상태가 언제 변화할지는 예측 불가능한 영역에 속한다. 그러나 실시간 시스템(Real-Time System) 애플리케이션은 이러한 비동기적 사건들을 결정론적(Deterministic)인 제어 흐름 내에서 처리해야 하는 요구사항을 갖는다. DDS 표준은 이러한 비동기적 이벤트를 동기적 실행 흐름으로 변환하여 애플리케이션이 주도권을 가지고 데이터를 처리할 수 있도록 돕는 강력한 메커니즘을 제공하는데, 이것이 바로 WaitSetCondition 모델이다.1

본 7.1절에서는 DDS 사양(Specification)이 정의하는 동기 대기 모델의 철학적 배경부터, WaitSet 클래스의 내부 아키텍처, 다양한 Condition 객체들의 상호작용, 그리고 리스너(Listener) 모델과의 심층적인 비교 분석을 통해 고성능 분산 시스템에서의 이벤트 처리 전략을 상세히 기술한다.

1. 비동기 통신과 동기적 제어의 딜레마

분산 시스템 설계에 있어 가장 근본적인 난제는 ’시간(Time)’과 ’공간(Space)’의 분리다. 발행자(Publisher)는 구독자(Subscriber)가 언제 데이터를 소비할지 알 수 없으며, 구독자는 데이터가 언제 도착할지 알 수 없다. 이러한 불확실성 속에서 애플리케이션이 데이터를 인지하는 방식은 크게 두 가지로 대별된다.

  1. 비동기 알림(Asynchronous Notification): 미들웨어가 데이터 도착 즉시 애플리케이션의 코드를 호출(Callback)하는 방식. DDS의 Listener가 이에 해당한다.
  2. 동기 대기(Synchronous Wait): 애플리케이션이 자신의 실행 흐름을 멈추고 특정 사건이 발생할 때까지 대기하는 방식. DDS의 WaitSet이 이에 해당한다.2

리스너 방식은 반응성(Responsiveness) 측면에서 우수해 보일 수 있으나, 미들웨어의 내부 스레드 컨텍스트에서 애플리케이션 로직이 실행된다는 위험성을 내포한다. 이는 데드락(Deadlock)이나 자원 경합(Race Condition)을 유발할 수 있는 치명적인 요인이 된다.3 반면, 동기 대기 모델은 운영체제의 입출력 다중화(I/O Multiplexing) 모델인 select()poll()과 유사한 철학을 공유하며, 애플리케이션이 명시적으로 제어권을 행사할 수 있는 안전한 환경을 제공한다. WaitSet은 단순한 대기 도구가 아니라, 비동기적인 네트워크 이벤트를 동기적인 애플리케이션 로직으로 변환해 주는 **임피던스 매처(Impedance Matcher)**로서 기능한다.5

2. WaitSet 클래스의 아키텍처 및 위상

OMG DDS 표준 명세(Specification)에서 WaitSet은 애플리케이션과 미들웨어 간의 상호작용을 중재하는 독립적인 인터페이스로 정의된다. 구조적으로 WaitSetCondition 객체들을 담는 컨테이너이자, 이들의 상태 변화를 감지하여 스레드의 블로킹(Blocking)을 해제하는 신호기 역할을 수행한다.

2.1 클래스 상속 계층과 독립성

DDS의 대부분의 주요 객체들(Topic, DataReader, DataWriter 등)은 Entity 클래스를 상속받아 QoS(Quality of Service) 정책과 Listener, StatusCondition을 포함하는 구조를 가진다. 그러나 WaitSetEntity를 상속받지 않는 독립적인 객체다.1 이는 WaitSet이 도메인 참여자(DomainParticipant)나 데이터 통신 자체에 종속된 존재가 아니라, 애플리케이션의 실행 흐름을 제어하기 위한 별도의 유틸리티임을 시사한다.

하지만 구현 관점(Platform Specific Model, PSM)에서 WaitSet은 일반적으로 팩토리 패턴이 아닌 직접적인 할당(예: new WaitSet())을 통해 생성되며, 이는 WaitSet이 특정 도메인에 묶이지 않고 여러 도메인 참여자 간의 이벤트를 통합 관리할 수 있음을 의미한다.7

2.2 WaitSet과 Condition의 관계성 (Association)

WaitSetConditionN:M (다대다) 관계를 맺을 수 있는 구조를 가진다.

  • 1개의 WaitSet에 N개의 Condition: 애플리케이션은 하나의 스레드에서 ‘데이터 도착(ReadCondition)’, ‘네트워크 단절(StatusCondition)’, ‘종료 신호(GuardCondition)’ 등 서로 다른 성격의 이벤트를 동시에 감시할 수 있다.
  • 1개의 Condition을 M개의 WaitSet에 부착: 이론적으로는 가능하나, 실제 구현 및 스레드 안전성 문제로 인해 권장되지 않거나 제한될 수 있다. 특히 동일한 WaitSet에 대해 여러 스레드가 동시에 wait()를 호출하는 것은 금지되어 있다(Not allowable).9

2.3 블로킹(Blocking)과 언블로킹(Unblocking) 메커니즘

WaitSet의 핵심 연산인 wait()는 호출한 스레드를 블로킹(BLOCKED) 상태로 전환시킨다. 블로킹은 CPU 사이클을 소모하지 않는 대기 상태(Sleep)를 의미하며, 이는 OS 레벨의 동기화 원시(Primitive)인 세마포어(Semaphore)나 조건 변수(Condition Variable)를 통해 구현된다.10

스레드가 WaitSet의 장벽(Barrier)을 넘어 언블로킹(UNBLOCKED) 되는 조건은 다음과 같다.

  1. 조건 충족(Triggered): 부착된 Condition 중 하나 이상의 trigger_valueTRUE로 전이되었을 때.
  2. 타임아웃(Timeout): wait() 호출 시 인자로 전달한 Duration_t 시간이 경과했을 때.
  3. 수동 해제: 다른 스레드에서 GuardCondition 등을 통해 강제로 trigger_value를 변경했을 때.9

이러한 메커니즘은 **리액터 패턴(Reactor Pattern)**의 전형적인 구현이다. WaitSet은 여러 이벤트 소스를 디멀티플렉싱(Demultiplexing)하여, 이벤트가 발생한 구체적인 Condition 객체들의 목록(active_conditions)을 반환하고, 애플리케이션은 이 목록을 순회하며 적절한 핸들러를 실행한다.11

3. Condition 클래스 계층 구조와 트리거 원리

Condition은 모든 대기 가능한 조건들의 최상위 추상 인터페이스(Root Interface)이다. 모든 Condition 객체는 get_trigger_value()라는 연산을 가지며, 이는 현재 조건이 충족되었는지 여부를 Boolean 값으로 반환한다.1 DDS 표준은 이를 상속하는 구체적인 조건 클래스들을 정의하여 다양한 유형의 이벤트를 처리한다.

3.1 StatusCondition: 통신 상태 변화의 감지

StatusConditionEntity(DataReader, DataWriter, Topic, DomainParticipant)와 1:1로 결합된 조건 객체다. 각 Entity는 통신과 관련된 다양한 상태(Status)를 가지며, StatusCondition은 이러한 상태 변화를 감지하여 WaitSet을 깨운다.15

  • 동작 원리: StatusConditiontrigger_value는 엔티티의 **변경된 상태 플래그(ChangedStatusFlag)**들과 사용자가 설정한 **활성화 마스크(EnabledStatuses)**의 논리적 AND 연산 결과에 의존한다. 즉, 사용자가 관심을 가진 상태(Mask)에 변화가 생겼을 때만 트리거된다.
  • 레벨 트리거(Level-Triggered) 특성: StatusCondition은 상태가 변경된 사실이 해소(Reset)되지 않는 한 TRUE 상태를 유지한다. 예를 들어, DATA_AVAILABLE_STATUS가 트리거 되어 WaitSet이 반환되었으나 애플리케이션이 데이터를 읽지 않고 다시 wait()를 호출하면, 조건이 여전히 참이므로 즉시 반환된다(Busy Loop 발생). 따라서 개발자는 반드시 데이터를 읽거나(Read/Take), get_status_changes() 등을 호출하여 상태를 명시적으로 초기화해야 한다.9
  • 설정 API: set_enabled_statuses() 연산을 통해 감시하고자 하는 상태(예: 데이터 도착, 데드라인 위반, 구독자 매칭 등)를 선택적으로 활성화할 수 있다.18

3.2 ReadCondition: 데이터 중심의 정교한 제어

StatusConditionDATA_AVAILABLE_STATUS가 단순히 “데이터가 도착했다“는 사실만을 알려준다면, ReadCondition은 **“어떤 상태의 데이터가 있는가”**를 구체적으로 필터링하여 대기할 수 있게 해준다. ReadConditionDataReader에 특화된 조건으로, 데이터의 생명주기 상태를 기반으로 트리거 여부를 결정한다.12

ReadCondition은 다음 세 가지 상태 마스크(Mask)의 조합으로 정의된다:

  1. SampleState: 데이터가 이전에 읽혔는가? (READ, NOT_READ)
  2. ViewState: 이 인스턴스에 대한 첫 번째 갱신인가? (NEW, NOT_NEW)
  3. InstanceState: 데이터 인스턴스가 유효한가? (ALIVE, NOT_ALIVE_DISPOSED, NOT_ALIVE_NO_WRITERS)

활용 예시:

NOT_READ_SAMPLE_STATE + NEW_VIEW_STATE + ALIVE_INSTANCE_STATE

위 조합으로 ReadCondition을 생성하면, “아직 읽지 않았고, 이 리더가 처음 보는 인스턴스이며, 살아있는 상태“의 데이터가 도착했을 때만 WaitSet을 깨운다. 이미 읽은 데이터나 종료된 인스턴스 정보는 무시하므로 불필요한 웨이크업(Wake-up)을 방지하고 CPU 효율을 극대화한다.20

3.3 QueryCondition: 콘텐츠 기반 필터링 (Content-Based Filtering)

QueryConditionReadCondition을 상속받는 특수 형태로, 데이터의 메타데이터(상태)뿐만 아니라 **데이터의 내용(Content/Payload)**까지 검사하여 트리거 여부를 결정한다.19 이는 SQL의 WHERE 절과 유사한 문법을 사용하여 필터 표현식(Filter Expression)을 정의한다.

  • 필터링 메커니즘: 수신된 데이터가 역직렬화되어 캐시에 저장된 후, QueryCondition에 정의된 표현식(Expression)을 평가한다. 표현식이 TRUE일 때만 해당 조건의 trigger_valueTRUE로 전환된다.
  • 동적 파라미터: 쿼리 표현식은 %0, %1과 같은 위치 지정 파라미터를 포함할 수 있으며, set_query_parameters()를 통해 런타임에 동적으로 필터 기준을 변경할 수 있다. 이는 재컴파일 없이 필터 로직을 변경할 수 있는 유연성을 제공한다.23
  • ContentFilteredTopic과의 차이:
  • ContentFilteredTopic: 송신 측(Writer) 또는 네트워크 레벨에서 데이터를 필터링하여 수신 측으로 전송되는 데이터 양 자체를 줄인다(Network Bandwidth 절약).
  • QueryCondition: 수신 측(Reader) 캐시에 이미 도착한 데이터 중, 애플리케이션이 지금 당장 처리하고 싶은 데이터만 선별하여 접근(View)한다(Application Logic 제어). WaitSetQueryCondition을 통해 데이터의 내용에 따라 선택적으로 깨어날 수 있다.25

[표 7.1-1] DDS 쿼리 및 필터 표현식 지원 연산자 요약 26

카테고리연산자예시비고
비교 연산자=, <>, <, >, <=, >=x > 100, id <> 5기본 수치 및 문자열 비교
논리 연산자AND, OR, NOTa < 10 AND b > 5조건 결합
범위/집합BETWEEN, INx BETWEEN 1 AND 10IN ('RED', 'BLUE')
문자열 매칭LIKEname LIKE 'M%'와일드카드(%, _) 지원
파라미터%0, %1,…val > %0런타임 동적 바인딩

3.4 GuardCondition: 사용자 정의 이벤트 및 흐름 제어

GuardCondition은 미들웨어의 내부 상태나 데이터 통신과 무관하게, 애플리케이션이 직접 제어할 수 있는 유일한 조건 객체다. 이는 주로 멀티스레드 환경에서 WaitSet에 대기 중인 스레드를 외부에서 깨워야 할 때 사용된다.18

  • 주요 용도:
  1. 애플리케이션 종료: 대기 중인 스레드에게 종료 신호를 보내 안전하게 루프를 탈출시킬 때.
  2. 설정 변경 알림: 런타임에 QoS가 변경되거나 모드 스위칭이 필요할 때.
  3. 이벤트 통합: DDS 이외의 이벤트(예: 하드웨어 인터럽트, 타이머)를 DDS 이벤트 루프 안으로 통합하고자 할 때.
  • 동작: set_trigger_value(TRUE)를 호출하면 해당 조건이 부착된 모든 WaitSet이 즉시 언블로킹된다. 이는 유닉스의 파이프(Pipe)나 이벤트FD(eventfd)를 통한 시그널링과 유사한 역할을 수행한다.11

4. WaitSet의 내부 동작 메커니즘과 상태 전이

WaitSet의 내부 동작은 운영체제 커널의 스케줄링 메커니즘과 밀접하게 연관되어 있다. 시스템 수준에서 보았을 때 WaitSet은 **이벤트 디스패처(Event Dispatcher)**이자 스레드 장벽(Thread Barrier) 역할을 동시에 수행한다.

4.1 블로킹과 시그널링의 원자성 (Atomicity)

WaitSet은 스레드를 블로킹 상태로 만들 때 경쟁 상태(Race Condition)를 방지하기 위해 정교한 원자적 연산을 수행한다.

  1. Wait 진입: wait()가 호출되면 먼저 현재 부착된 모든 조건들의 trigger_value를 검사한다.
  2. 즉시 반환: 만약 이미 TRUE인 조건이 하나라도 있다면 블로킹 없이 즉시 반환된다.
  3. 블로킹: 모든 조건이 FALSE라면, 스레드는 대기 큐(Wait Queue)에 등록되고 커널에 의해 재워진다(Sleep).
  4. 시그널링: 데이터 도착 등으로 인해 미들웨어 스레드가 조건의 상태를 변경하면, 해당 조건이 부착된 WaitSet에 시그널을 보내 스레드를 깨운다. 이때, 여러 조건이 동시에 만족되더라도 스레드는 단 한 번만 깨어난다.1

일부 문헌에서는 WaitSet을 “객체지향적인 select()“라고 표현하지만, 실제 구현(RTI Connext 등)에서는 select() 시스템 콜보다는 **바이너리 세마포어(Binary Semaphore)**나 **조건 변수(Condition Variable)**를 사용하여 더 가볍고 빠른 동기화를 구현하는 경우가 많다.11 이는 파일 디스크립터 제한(File Descriptor Limit)에 구애받지 않고 수천 개의 조건을 감시할 수 있게 한다.

4.2 상태 전이 시나리오 (Trigger Propagation)

DDS 구현체는 데이터가 네트워크로부터 도착하여 역직렬화(Deserialization)되고 DataReader의 캐시에 저장되는 순간, 관련된 Condition들의 trigger_value를 갱신한다.

  • 전파 순서:
  1. 데이터 수신 -> DataReader 캐시 업데이트.
  2. ReadCondition / QueryCondition 평가 및 플래그 설정.
  3. StatusCondition (DATA_AVAILABLE) 플래그 설정.
  4. 연관된 WaitSet에 시그널 전송.
  5. WaitSet 대기 스레드 기상 (Wake-up).
  6. wait() 함수 반환 및 active_conditions 목록 전달.

이 과정에서 중요한 점은 상태의 일관성이다. 스레드가 깨어난 직후 다른 스레드가 데이터를 가로채서(Take) 가져가 버릴 경우, ReadCondition은 다시 FALSE가 될 수 있다. 따라서 WaitSet이 반환한 active_conditions 목록에 있는 조건이라 할지라도, 실제 처리 시점에는 더 이상 유효하지 않을 수 있음을(예: 데이터 없음) 감안하고 로직을 작성해야 한다.12

5. 동기 대기 모델의 구현 패턴 및 모범 사례

WaitSet을 올바르게 사용하는 것은 단순히 API를 호출하는 것을 넘어, 효율적이고 안전한 이벤트 루프를 설계하는 것이다. 실무에서 권장되는 주요 구현 패턴과 주의사항을 살펴본다.

5.1 기본 대기 루프 (The Basic Wait Loop)

가장 전형적인 사용 패턴은 무한 루프 내에서 wait()를 호출하고, 반환된 조건을 검사하여 데이터를 처리하는 방식이다.

C++

// [코드 7.1-1] WaitSet을 이용한 기본 이벤트 루프 구조 (C++ 예시)
DDS::WaitSet* ws = new DDS::WaitSet();
ws->attach_condition(status_cond);
ws->attach_condition(read_cond);
DDS::ConditionSeq active_conditions;
DDS::Duration_t timeout = {1, 0}; // 1초 타임아웃

while (running) {
DDS::ReturnCode_t ret = ws->wait(active_conditions, timeout);

if (ret == DDS::RETCODE_OK) {
for (int i = 0; i < active_conditions.length(); ++i) {
if (active_conditions[i] == status_cond) {
// 상태 변경 처리 (예: Liveliness Lost)
process_status_change();
} else if (active_conditions[i] == read_cond) {
// 데이터 처리: take_w_condition 사용 권장
// ReadCondition에 부합하는 데이터만 효율적으로 인출
reader->take_w_condition(data_seq, info_seq, DDS::LENGTH_UNLIMITED, read_cond);
process_data(data_seq);
reader->return_loan(data_seq, info_seq);
}
}
} else if (ret == DDS::RETCODE_TIMEOUT) {
// 주기적인 헬스 체크나 유지보수 작업 수행
perform_maintenance();
}
}

이 패턴에서 take_w_condition()을 사용하는 것이 중요하다. 일반적인 take()는 큐의 모든 데이터를 가져오지만, take_w_condition()은 해당 조건을 만족시킨(트리거한) 데이터만을 정확히 가져오므로 탐색 비용을 줄여준다.21

5.2 다중 조건의 결합 논리 (AND vs OR)

기본적으로 WaitSet에 부착된 조건들은 논리적 OR 관계로 동작한다. 즉, “조건 A 또는 조건 B가 참이면 깨어난다”. 그러나 특정 시나리오에서는 “조건 A와 조건 B가 모두 참일 때(AND)“만 처리하고 싶을 수 있다.

DDS 표준 API 자체는 WaitSet 레벨에서 AND 논리를 직접 지원하지 않는다. 이를 구현하기 위해서는 애플리케이션 레벨의 로직이 필요하다.8

  1. wait()는 어느 하나라도 만족하면 반환된다.
  2. 반환 후 애플리케이션은 필요한 모든 조건이 active_conditions 목록에 포함되어 있는지, 또는 각 조건의 get_trigger_value()가 모두 TRUE인지 확인한다.
  3. 만족하지 않으면 다시 wait()를 호출한다. 이 경우 타임아웃을 짧게 주거나 폴링 방식으로 전환하는 전략이 필요할 수 있다.

5.3 GUI 및 메인 루프와의 통합 (Integration with Main Loops)

GUI 애플리케이션(Qt, MFC, C# WPF 등)이나 게임 엔진은 자체적인 메인 이벤트 루프를 가지고 있다. 이 루프 내에서 블로킹 함수인 wait()를 호출하면 화면이 멈추는 현상(Freezing)이 발생한다. 따라서 WaitSet을 메인 스레드에서 직접 사용하는 것은 지양해야 한다.29

  • 전용 스레드 전략(Worker Thread): 별도의 스레드를 생성하여 WaitSet 루프를 돌리고, 데이터가 수신되면 스레드 안전한 큐(Thread-safe Queue)나 시그널/슬롯(Qt의 경우) 메커니즘을 통해 GUI 스레드로 데이터를 전달해야 한다.
  • 0 타임아웃 폴링: wait()의 타임아웃을 0으로 설정하여 폴링(Polling) 방식으로 GUI 루프 내에 삽입할 수도 있다. 예를 들어 게임 루프의 update() 함수 내에서 체크하는 방식이다. 그러나 이는 빈번한 컨텍스트 스위칭과 시스템 콜을 유발하여 CPU 사용량을 증가시킬 수 있으므로 주의해야 한다.30

6. WaitSet vs Listener: 심층 비교 및 선택 가이드

개발자는 언제 WaitSet을 쓰고 언제 Listener를 써야 하는가? 이 질문은 시스템의 성능 요구사항, 안전성, 그리고 아키텍처의 복잡도에 따라 결정된다.

[표 7.1-2] WaitSet 모델과 Listener 모델의 상세 비교 분석 3

비교 항목Listener (비동기, Push)WaitSet (동기, Pull)
실행 주체미들웨어 내부 스레드애플리케이션 소유 스레드
알림 방식이벤트 발생 시 즉시 콜백 호출애플리케이션이 준비되었을 때 수신
반응 속도(Latency)최저 (Lowest Latency) 컨텍스트 스위칭 없음약간 높음 스레드 스케줄링 및 깨어남 비용 발생
처리량(Throughput)높을 수 있으나 병목 위험 존재높음 데이터 배치(Batch) 처리에 유리
안전성(Safety)낮음 (데드락 위험 높음)높음 (스레드 분리 및 제어 용이)
흐름 제어어려움 (Data Flood 시 오버헤드)용이함 (Back-pressure 자연 발생)
복잡도상대적으로 낮음 (단순 이벤트)상대적으로 높음 (루프 및 조건 관리)
주 사용처단순 로깅, 알람, 초저지연 반응복잡한 데이터 처리, UI 연동, 다중 센서 융합

핵심 인사이트: 리스너 내부에서는 파일 I/O, 무거운 연산, 또는 다른 DDS 호출(특히 Write)을 수행해서는 안 된다. 이는 미들웨어의 수신 스레드를 차단하여 전체 통신 마비를 일으킬 수 있기 때문이다. 또한 리스너에서 뮤텍스(Mutex)를 잘못 사용하면 미들웨어 내부 락(Lock)과 얽혀 데드락이 발생할 확률이 매우 높다.4 반면 WaitSet은 애플리케이션 스레드에서 동작하므로 긴 연산을 수행하거나 블로킹 I/O를 수행해도 전체 통신 시스템에 영향을 주지 않는다. 따라서 복잡한 데이터 처리가 필요한 대부분의 실제 응용 프로그램에서는 WaitSet 모델이 아키텍처적으로 훨씬 견고하고 안전한 선택이다.

7. 성능 최적화 및 고급 활용 전략

WaitSet을 활용하여 시스템의 성능을 극대화하기 위한 전략들은 다음과 같다.

7.1 제로 카피(Zero-Copy)와 WaitSet

대용량 데이터(예: 영상, 라이다 포인트 클라우드)를 처리할 때, WaitSettake() 연산을 결합하면 메모리 복사를 최소화할 수 있다. 일부 고성능 DDS 구현체(Iceoryx 기반 등)는 공유 메모리(Shared Memory)를 활용하며, WaitSet을 통해 데이터 포인터만을 전달받아 처리 후 반환(Return Loan)하는 방식을 지원한다. 이는 데이터 복사 오버헤드를 제거하여 처리량을 획기적으로 높인다.14

7.2 배치 처리(Batch Processing)

데이터가 매우 빈번하게 도착하는 경우, 매번 WaitSet이 깨어나는 것은 비효율적이다. QoS 설정을 통해 데이터를 배치(Batch)로 묶어 전송받거나, 애플리케이션 로직에서 WaitSet이 깨어난 후 active_conditions를 처리할 때 루프를 돌며 쌓여있는 데이터를 한꺼번에 가져오는(Take All) 전략을 사용하여 시스템 콜 호출 빈도를 줄여야 한다.

8. 결론 및 제언

7.1절에서 살펴본 바와 같이, 동기 대기 모델과 WaitSet은 DDS를 단순한 메시지 패싱 도구에서 고성능 이벤트 구동형 아키텍처(Event-Driven Architecture)의 핵심 컴포넌트로 격상시킨다. 리스너가 제공하는 즉각성에 현혹되기 쉽지만, 시스템의 규모가 커지고 로직이 복잡해질수록 WaitSet이 제공하는 **제어권의 명확성(Control Clarity)**과 **스레드 안전성(Thread Safety)**은 대체 불가능한 가치를 지닌다.

성공적인 DDS 시스템 설계를 위해 개발자는 다음 세 가지 원칙을 견지해야 한다.

  1. 역할의 분리: 단순 알림은 리스너로, 데이터 처리는 WaitSet으로 분리하여 설계하라.
  2. 조건의 정교화: ReadConditionQueryCondition을 적극 활용하여 불필요한 웨이크업을 최소화하라.
  3. 자원 관리의 철저함: WaitSetCondition 객체의 생명주기를 명확히 하고, 특히 멀티스레드 환경에서의 부착/탈착 시점을 엄격히 통제하라.

이어지는 7.2절에서는 이러한 WaitSet을 활용하여 실제로 데이터를 읽고 처리하는 다양한 데이터 접근 패턴(take vs read, Zero-Copy 등)에 대해 구체적으로 다룰 것이다.

9. 참고 자료

  1. Data Distribution Service (DDS) - Object Management Group (OMG), https://www.omg.org/spec/DDS/1.4/PDF
  2. OMG Data-Distribution Service: Architectural Overview, https://d2vkrkwbbxbylk.cloudfront.net/sites/default/files/DDS_Architectural_Overview.pdf
  3. Use WaitSets, Except When You Need Extreme Latency, https://community.rti.com/best-practices/use-waitsets-except-when-you-need-extreme-latency
  4. Package: DDS.Listener - RTI Community, https://community.rti.com/static/documentation/connext-dds/current/doc/api/connext_dds/api_ada/dds-listener.ads.html
  5. NDDS Latency and Throughput - DDS Foundation, https://www.dds-foundation.org/sites/default/files/Evaluating_Performance_Publish_Subscribe_Platforms.pdf
  6. DDS — Open Issues - OMG Issue Tracker, https://issues.omg.org/issues/spec/DDS
  7. RTI Connext C API: Waitset Use Cases, https://community.rti.com/static/documentation/connext-dds/current/doc/api/connext_dds/api_c/group__DDSWaitsetExampleModule.html
  8. WaitSet with Status Condition | Data Distribution Service (DDS …, https://community.rti.com/examples/waitset-status-condition
  9. Package: DDS.WaitSet - RTI Community, https://community.rti.com/static/documentation/connext-dds/7.3.0/doc/api/connext_dds/api_ada/dds-waitset.ads.html
  10. Waiting for Conditions - RTI Community, https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/users_manual/users_manual/Waiting_for_Conditions.htm
  11. waiting on multiple filedescriptor/objects - RTI Community, https://community.rti.com/forum-topic/waiting-multiple-filedescriptorobjects
  12. 3.1.4. Conditions and Wait-sets - eProsima Fast DDS, https://fast-dds.docs.eprosima.com/en/v2.6.10/fastdds/dds_layer/core/waitsets/waitsets.html
  13. WaitSets and Conditions — Eclipse Cyclone DDS, 0.11.0, https://cyclonedds.io/docs/cyclonedds/latest/api/waitset.html
  14. Overview - iceoryx.io, https://iceoryx.io/v1.0.2/getting-started/overview/
  15. Tutorial on the OMG Data Distribution Service, http://www.dre.vanderbilt.edu/~gokhale/OMG_RTWS06/00-T1-1_Giddings.pdf
  16. RTI Connext Java API: WaitSet Class Reference - RTI Community, https://community.rti.com/static/documentation/connext-dds/current/doc/api/connext_dds/api_java/classcom_1_1rti_1_1dds_1_1infrastructure_1_1WaitSet.html
  17. Package: DDS.WaitSet - RTI Community, https://community.rti.com/static/documentation/connext-dds/current/doc/api/connext_dds/api_ada/dds-waitset.ads.html
  18. RTI Connext C API: Conditions and WaitSets - RTI Community, https://community.rti.com/static/documentation/connext-dds/current/doc/api/connext_dds/api_c/group__DDSConditionsModule.html
  19. Introduction to DDS - OpenDDS 3.27.0, https://opendds.readthedocs.io/en/dds-3.27/devguide/introduction_to_dds.html
  20. 3.1.4. Conditions and Wait-sets - 3.4.1 - eProsima Fast DDS, https://fast-dds.docs.eprosima.com/en/3.x/fastdds/dds_layer/core/waitsets/waitsets.html
  21. 44.3 Accessing DDS Data Samples with Read or Take, https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/users_manual/users_manual/AccessingData_Samples_ReadTake.htm
  22. 20.1.4.1. DataReader - 3.4.1 - eProsima Fast DDS, https://fast-dds.docs.eprosima.com/en/3.x/fastdds/api_reference/dds_pim/subscriber/datareader.html
  23. How to Filter Topic Content : Query Conditions and Content Filtering, https://kbase.zettascale.tech/article/how-can-i-filter-my-topic-content/
  24. DDS::QueryCondition Class Reference - Twin Oaks Computing, Inc, https://www.twinoakscomputing.com/documents/refman_html_4.0.10/CoreDX_DDS_CPP_Reference_4.0.10/classDDS_1_1QueryCondition.html
  25. What is the difference between QueryConditions … - RTI Community, https://community.rti.com/kb/what-difference-between-queryconditions-and-contentfilteredtopics
  26. 3.5.9. The default SQL-like filter - 3.4.1 - eProsima Fast DDS, https://fast-dds.docs.eprosima.com/en/3.x/fastdds/dds_layer/topic/contentFilteredTopic/defaultFilter.html
  27. RTI Connext Modern C++ API: Queries and Filters Syntax, https://community.rti.com/static/documentation/connext-dds/current/doc/api/connext_dds/api_cpp2/group__DDSQueryAndFilterSyntaxModule.html
  28. CoreDX Data Distribution Service: DDS::DataReader Class Reference, https://www.twinoakscomputing.com/documents/refman_html_3.6.8/CoreDX_DDS_CPP_Reference_3.6.8/classDDS_1_1DataReader.html
  29. Qt and RTI DDS interaction—Need some guidance - Stack Overflow, https://stackoverflow.com/questions/17834696/qt-and-rti-dds-interaction-need-some-guidance
  30. DDS Reader not dropping messages - java - Stack Overflow, https://stackoverflow.com/questions/60537723/dds-reader-not-dropping-messages
  31. iceoryx2/ROADMAP.md at main - GitHub, https://github.com/eclipse-iceoryx/iceoryx2/blob/main/ROADMAP.md