콘텐츠로 이동
무료 평가 시작

pdcomm::Secs1Endpoint

클래스

호출자가 제공하는 시리얼 I/O 위에서 동작하는 SECS-I(SEMI E4) 끝점(endpoint) 하나를 소유하는 이동 전용 객체입니다.

class Secs1Endpoint

선언 위치: #include <pdcomm_secs1.hpp>

끝점은 SEMI E4 블록 전송 프로토콜을 실행합니다. ENQ/EOT 회선 제어, 마스터/슬레이브 경합(contention), 길이 바이트와 10바이트 헤더, 체크섬을 갖춘 최대 244 데이터 바이트의 블록(block), ACK/NAK 응답, 재시도, 중복 블록 감지, 다중 블록 메시지 재조립을 처리합니다. 시리얼 포트를 열지는 않습니다. 생성자에 전달한 I/O 객체(Secs1IoAdapter 또는 Secs1BorrowedIo)가 비차단(non-blocking) 읽기·쓰기 콜백을 제공하며, 호출자는 자체 시계로 poll()을 호출해 끝점을 구동합니다.

끝점은 메시지 전송만 담당합니다. 응답을 1차 메시지(primary message)와 짝짓거나, T3 응답 타이머를 실행하거나, 수신 메시지를 장치 ID나 방향으로 거르거나, 본문을 SECS-II로 해석하지 않습니다. 응답은 애플리케이션에서 system_bytes로 짝지으십시오.

수명 주기: 생성하고 start()를 호출한 뒤 poll(), submit()을 호출하고 nextEvent()로 이벤트를 모두 꺼냅니다. 결함(fault)이 발생하면 reset()을 호출할 때까지 모든 I/O가 멈춥니다. stop()은 콜백을 호출하지 않고 모든 런타임 상태를 버리며, 이후 start()를 호출하면 새 세대(generation)가 시작됩니다.

pdcomm::Secs1IoAdapter<SerialPort> io;
pdcomm::Secs1Endpoint endpoint(io, options);
endpoint.start();
while (running) {
    endpoint.poll(nowMilliseconds());
    while (auto event = endpoint.nextEvent()) {
        const auto info = event.info();
        if (info.kind == PDCOMM_SECS1_EVENT_INBOUND) {
            std::vector<uint8_t> body = event.body();
            // Decode the body; answer with submit() when info.reply_expected is 1.
        }
    }
}
endpoint.stop();

참고

  • 이동 전용입니다. 네이티브 끝점은 자신을 생성한 스레드에 묶입니다. 소멸을 포함한 모든 멤버를 그 스레드에서 호출하십시오. 다른 스레드에서의 호출, 동시 호출, 콜백 안에서의 호출은 PDCOMM_INVALID_STATE와 함께 pdcomm::Error를 던집니다. 다른 스레드나 콜백 안에서 소멸하면 아무 일도 하지 않으며 네이티브 끝점이 누수됩니다. 래퍼를 이동해도 묶인 스레드는 바뀌지 않습니다. 이동된 후의 끝점은 핸들을 소유하지 않으며, 그 호출은 PDCOMM_INVALID_ARGUMENT와 함께 예외를 던집니다. 내부 패닉(panic)이 발생한 뒤에는 state()를 제외한 모든 호출이 PDCOMM_POISONED와 함께 예외를 던지며, state()는 poisoned를 보고합니다.

멤버

Secs1Endpoint

생성자

pdcomm_secs1_create()로 정지 상태의 SECS-I 끝점을 만듭니다.

template <typename Io> Secs1Endpoint(Io &io, const PdcommSecs1Options &options)

선언 위치: #include <pdcomm_secs1.hpp>

어느 콜백도 호출하지 않고 콜백 테이블과 옵션을 검증한 뒤 복사하고, 끝점을 호출한 스레드에 묶습니다. 새 끝점의 세대(generation)는 1이며, 시작하고 폴링하기 전에는 I/O를 수행하지 않습니다.

매개변수

이름설명
IoSecs1IoAdapter 또는 Secs1BorrowedIo이거나, native() 멤버가 const PdcommSecs1Io &를 반환하는 임의의 형식입니다.
ioI/O 바인딩입니다. 빌려 쓰므로 끝점보다 오래 살아 있어야 합니다.
options회선 설정과 한도입니다. 모든 타이머는 호출자의 틱(tick) 단위로 나타낸 0이 아닌 시간이며, 모든 한도는 애플리케이션 정책입니다. PDComm은 SEMI E4 기본값으로 대체하지 않습니다. 호출 중에 복사됩니다.

참고

  • 예외 pdcomm::Error: 콜백 테이블에 nullptr 컨텍스트나 콜백이 있거나, struct_size가 너무 작거나, version 또는 예약 필드가 잘못되었거나, priority를 알 수 없거나, 타이머가 0이거나, 한도가 0이거나 서로 맞지 않으면 PDCOMM_INVALID_ARGUMENT입니다. 이벤트 큐를 확보할 수 없으면 PDCOMM_ALLOCATION_FAILED, 프로세스의 끝점 식별자가 소진되면 PDCOMM_LIMIT_EXCEEDED, 라이브러리가 내부 패닉을 격리(contain)했으면 PDCOMM_INTERNAL_ERROR입니다.

Secs1Endpoint

생성자

other가 소유한 네이티브 핸들의 소유권을 가져옵니다.

Secs1Endpoint(Secs1Endpoint &&other) noexcept

선언 위치: #include <pdcomm_secs1.hpp>

네이티브 끝점은 계속 자신을 생성한 스레드에 묶여 있습니다.

매개변수

이름설명
other원본 래퍼입니다. 빈 상태가 됩니다.

Secs1Endpoint

생성자

복사할 수 없습니다. 래퍼가 네이티브 핸들을 단독으로 소유합니다.

Secs1Endpoint(const Secs1Endpoint &) = delete

선언 위치: #include <pdcomm_secs1.hpp>

nativeHandle

메서드

C API를 직접 호출할 수 있도록 소유한 네이티브 핸들을 반환합니다.

PdcommSecs1Endpoint *nativeHandle() noexcept

선언 위치: #include <pdcomm_secs1.hpp>

반환값

핸들입니다. 이동된 후의 끝점이면 nullptr입니다. 소유권은 이 래퍼에 남습니다.

nativeHandle

메서드

읽기 전용 C API 호출을 위해 소유한 네이티브 핸들을 반환합니다.

const PdcommSecs1Endpoint *nativeHandle() const noexcept

선언 위치: #include <pdcomm_secs1.hpp>

반환값

핸들입니다. 이동된 후의 끝점이면 nullptr입니다. 소유권은 이 래퍼에 남습니다.

nextEvent

메서드

pdcomm_secs1_next_event()로 큐에서 가장 오래된 이벤트를 꺼냅니다.

Secs1Event nextEvent()

선언 위치: #include <pdcomm_secs1.hpp>

반환값

다음 이벤트입니다. 큐가 비어 있으면 빈 Secs1Event입니다.

참고

  • 예외 pdcomm::Error: 이벤트를 할당할 수 없으면 PDCOMM_ALLOCATION_FAILED입니다. 이때 이벤트는 대기 상태로 남고 다음 호출이 이를 반환하며, 그때까지 start(), poll(), submit(), reset(), stop()은 PDCOMM_BACKPRESSURE와 함께 예외를 던집니다. 끝점이 정지되었거나, 잘못된 스레드의 호출, 동시 호출, 재진입 호출이면 PDCOMM_INVALID_STATE입니다. 그 밖에 PDCOMM_POISONED가 있습니다.

operator=

메서드

현재 핸들을 해제한 뒤 other가 소유한 핸들의 소유권을 가져옵니다.

Secs1Endpoint &operator=(Secs1Endpoint &&other) noexcept

선언 위치: #include <pdcomm_secs1.hpp>

해제는 소멸자 규칙을 따르므로, 현재 끝점을 생성한 스레드에서 수행하십시오.

매개변수

이름설명
other원본 래퍼입니다. 빈 상태가 됩니다.

반환값

이 래퍼입니다.

operator=

메서드

복사 대입할 수 없습니다. 래퍼가 네이티브 핸들을 단독으로 소유합니다.

Secs1Endpoint &operator=(const Secs1Endpoint &) = delete

선언 위치: #include <pdcomm_secs1.hpp>

poll

메서드

pdcomm_secs1_poll()로 한 시간 조각 동안 회선 제어, 타이머, 콜백 I/O를 실행합니다.

size_t poll(uint64_t now)

선언 위치: #include <pdcomm_secs1.hpp>

호출마다 최대 PdcommSecs1Options::poll_budget개의 단계를 수행합니다. 회선이 유휴 상태이면 다음 송신 블록을 시작하고, 만료된 타이머를 처리하고, 받은 문자와 완료된 쓰기를 처리하며, 쓰기 콜백과 읽기 콜백 시도를 번갈아 수행합니다. 콜백은 이 호출 안에서만 실행됩니다. 결과는 이벤트로 큐에 들어가며, nextEvent()로 모두 꺼내야 합니다. 결함 상태의 끝점은 아무 작업도 하지 않고 0을 반환합니다.

매개변수

이름설명
now호출자의 틱으로 나타낸 현재 시각이며, *_ticks 옵션과 단위가 같습니다. 이전 호출에 전달한 값보다 작으면 안 됩니다.

반환값

수행한 단계의 수입니다.

참고

  • 예외 pdcomm::Error: 대기 중인 이벤트를 먼저 꺼내야 하거나 이벤트 큐가 가득 찼으면 PDCOMM_BACKPRESSURE입니다(대기 중인 단계는 유지되므로 이벤트를 꺼낸 뒤 다시 폴링하십시오). 끝점이 시작되지 않았거나, 잘못된 스레드의 호출, 동시 호출, 재진입 호출이면 PDCOMM_INVALID_STATE입니다. now가 이전 값보다 작거나 타이머 기한이 오버플로하면 PDCOMM_LIMIT_EXCEEDED, 내부 버퍼를 할당할 수 없으면 PDCOMM_ALLOCATION_FAILED, 내부 프로토콜 검사가 단계를 거부하면 PDCOMM_INVALID_ARGUMENT입니다. 그 밖에 PDCOMM_POISONED가 있습니다.
  • I/O 실패는 예외가 아닙니다. PDCOMM_SECS1_EVENT_FAULT 이벤트를 만들고 호출은 정상적으로 반환합니다.

reset

메서드

pdcomm_secs1_reset()로 종료성 결함을 지워 끝점이 다시 메시지를 전송할 수 있게 합니다.

void reset()

선언 위치: #include <pdcomm_secs1.hpp>

회선을 유휴 상태로 되돌리고, 대기 중인 쓰기, 중단된 제출, 일부만 받은 데이터를 버립니다. 큐에 있는 이벤트, 세대, 제출 번호는 유지됩니다.

참고

  • 예외 pdcomm::Error: 대기 중인 이벤트를 먼저 꺼내야 하면 PDCOMM_BACKPRESSURE입니다. 끝점이 시작되지 않았거나, 정지되었거나, 결함 상태가 아니거나, 잘못된 스레드의 호출, 동시 호출, 재진입 호출이면 PDCOMM_INVALID_STATE입니다. 그 밖에 PDCOMM_POISONED가 있습니다.

start

메서드

pdcomm_secs1_start()로 생성되었거나 정지된 끝점을 시작합니다.

void start()

선언 위치: #include <pdcomm_secs1.hpp>

시작은 I/O를 수행하지 않습니다. stop() 뒤에 시작하면 새 프로토콜 런타임을 만들고, 세대를 1 늘리며, 제출 번호를 1부터 다시 매깁니다.

참고

  • 예외 pdcomm::Error: 대기 중인(staged) 이벤트를 먼저 꺼내야 하면 PDCOMM_BACKPRESSURE입니다. 끝점이 이미 시작되었거나, 잘못된 스레드의 호출, 동시 호출, 재진입 호출이면 PDCOMM_INVALID_STATE입니다. 세대 카운터가 소진되면 PDCOMM_LIMIT_EXCEEDED, 새 런타임을 할당할 수 없으면 PDCOMM_ALLOCATION_FAILED입니다. 그 밖에 PDCOMM_POISONED가 있습니다.

state

메서드

pdcomm_secs1_state()로 끝점의 식별 정보와 수명 주기 플래그를 읽습니다.

PdcommSecs1State state()

선언 위치: #include <pdcomm_secs1.hpp>

시작 전과 정지 후를 포함한 모든 수명 주기 상태에서 유효하며, 대기 중인 이벤트에 막히지 않습니다. 끝점이 오염(poisoned)된 뒤에도 성공하는 유일한 호출이므로 poisoned를 보고할 수 있습니다.

반환값

끝점 ID, 세대, 그리고 started, stopped, faulted, poisoned 플래그입니다.

참고

  • 예외 pdcomm::Error: 잘못된 스레드의 호출, 동시 호출, 재진입 호출이면 PDCOMM_INVALID_STATE입니다. 상태를 읽는 동작 자체에서 패닉이 발생하면 PDCOMM_POISONED입니다.

stop

메서드

pdcomm_secs1_stop()로 시작된 끝점을 정지하고 런타임 상태를 버립니다.

void stop()

선언 위치: #include <pdcomm_secs1.hpp>

큐에 있는 이벤트, 보내고 있던 메시지, 일부만 받은 데이터를 이벤트 없이, 콜백도 호출하지 않고 버립니다. 이미 쓴 바이트는 회선에 남습니다. 끝점을 다시 시작할 때까지 nextEvent()는 PDCOMM_INVALID_STATE와 함께 예외를 던집니다.

참고

  • 예외 pdcomm::Error: 대기 중인 이벤트를 먼저 꺼내야 하면 PDCOMM_BACKPRESSURE입니다. 끝점이 시작되지 않았거나, 잘못된 스레드의 호출, 동시 호출, 재진입 호출이면 PDCOMM_INVALID_STATE입니다. 그 밖에 PDCOMM_POISONED가 있습니다.

submit

메서드

pdcomm_secs1_submit()로 전송할 메시지 하나를 큐에 넣습니다.

PdcommSecs1Token submit(const PdcommSecs1Message &message)

선언 위치: #include <pdcomm_secs1.hpp>

끝점은 한 번에 메시지 하나만 보냅니다. 현재 제출이 PDCOMM_SECS1_EVENT_OUTBOUND_COMPLETE, PDCOMM_SECS1_EVENT_OUTBOUND_FAILED 또는 결함을 만든 뒤에 다음 제출을 받습니다. 본문은 수락 시 복사되며 최대 244바이트의 블록으로 나뉩니다. 성공은 수락만을 뜻하며, 전송은 poll()에서 이루어집니다.

매개변수

이름설명
message보낼 메시지입니다. 필드는 SEMI E4 블록 헤더에 대응합니다. 장치 ID, 방향(R 비트), 스트림, 펑션, W 비트, 호출자가 정한 시스템 바이트입니다. 응답은 해당 1차 메시지의 시스템 바이트를 담습니다. 메시지와 본문은 계속 호출자가 소유하며, 호출이 반환되면 해제해도 됩니다.

반환값

제출 토큰입니다. 이 메시지의 송신 이벤트와 결함 이벤트에 그대로 다시 담깁니다.

참고

  • 예외 pdcomm::Error: 메시지 필드가 잘못되었거나 본문이 max_outbound_body_bytes, max_body_bytes, max_outbound_blocks 또는 max_blocks를 넘으면 PDCOMM_INVALID_ARGUMENT입니다. 대기 중인 이벤트를 먼저 꺼내야 하거나 다른 메시지를 아직 보내고 있으면 PDCOMM_BACKPRESSURE입니다. 끝점이 시작되지 않았거나 결함 상태이거나, 잘못된 스레드의 호출, 동시 호출, 재진입 호출이면 PDCOMM_INVALID_STATE입니다. 이 세대의 제출 번호가 소진되면 PDCOMM_LIMIT_EXCEEDED, 본문이나 블록을 복사할 수 없으면 PDCOMM_ALLOCATION_FAILED입니다. 그 밖에 PDCOMM_POISONED가 있습니다.

~Secs1Endpoint

메서드

콜백을 호출하지 않고 pdcomm_secs1_destroy()로 끝점을 해제합니다.

~Secs1Endpoint()

선언 위치: #include <pdcomm_secs1.hpp>

대기 중인 메시지, 큐에 있는 이벤트, 일부만 받은 데이터를 버립니다. 이미 쓴 바이트는 회선에 남습니다. 이미 꺼낸 이벤트는 계속 유효합니다. 끝점은 자신을 생성한 스레드에서 소멸하십시오. 다른 스레드나 콜백 안에서는 네이티브 끝점이 해제되지 않습니다. 빈 끝점은 아무것도 해제하지 않습니다.