Skip to content
Start free evaluation

pdcomm::GemEndpoint

Class

Common base of GemHost and GemEquipment: one HSMS endpoint with a GEM role.

class GemEndpoint

Declared in: #include <pdcomm_gem.hpp>

A GemEndpoint owns a TcpEndpoint (SEMI E37 HSMS) and the GEM state attached to it. It starts no threads and has no callbacks: your loop calls poll(), drains tcp().nextEvent(), and passes every event to handleEvent() in queue order. Requests return a PdcommTcpToken immediately; the reply arrives later as a GemResult whose GemResultInfo::token equals that token.

Both roles share the process program store and transfer calls (S7F1 to S7F6, plus the host-only S7F17 and S7F19) and, on equipment, the spool calls (S2F43/F44, S2F59/F60, S6F23/F24 and spooled delivery).

Throughout this class, a call fails with PDCOMM_BACKPRESSURE while a TCP event is staged but not yet handled, and with PDCOMM_POISONED after an internal panic.

pdcomm::GemEndpoint *endpoint = hostRole ? static_cast<pdcomm::GemEndpoint *>(host.get())
                                         : equipment.get();
endpoint->start();
while (running) {
    endpoint->poll();
    while (auto event = endpoint->tcp().nextEvent()) {
        auto result = endpoint->handle(event);
        // Inspect result.info() and act on it.
    }
}
endpoint->stop();

Notes

  • Move-only. Serialize all calls on one endpoint, including TCP calls, GEM calls and destruction; a quiescent endpoint may move to another thread. Calls that build temporary arrays can also throw std::bad_alloc.

Members

GemEndpoint

Constructor

Moves the endpoint; the source no longer owns a native endpoint.

GemEndpoint(GemEndpoint &&) noexcept = default

Declared in: #include <pdcomm_gem.hpp>

GemEndpoint

Constructor

Copying is disabled; the endpoint exclusively owns its native handle.

GemEndpoint(const GemEndpoint &) = delete

Declared in: #include <pdcomm_gem.hpp>

cancelProgramGrant

Method

Cancels the S7F1 grant activated by result.

void cancelProgramGrant(const GemResult &result)

Declared in: #include <pdcomm_gem.hpp>

Grants are identified by their original result, never by a matching program ID.

Parameters

NameDescription
resultResult of the S7F1 request that activated the grant.

Notes

  • Throws pdcomm::Error: PDCOMM_STALE_TOKEN when the grant is stale or no longer active; PDCOMM_INVALID_STATE when result is not an activated S7F1 request.

completeSpoolDelivery

Method

Finishes a spooled delivery attempt and, on success, removes the head entry.

GemSpoolWriteResult completeSpoolDelivery(GemResult &result, bool success)

Declared in: #include <pdcomm_gem.hpp>

For a W-bit message, report success only after inspecting the reply body against your own success policy; a matching function number alone is not success. For a message without W-bit, success means a complete local write, not peer receipt. Failure keeps the entry and stops the transmit run.

Parameters

NameDescription
resultDelivery result (GemOutcome::SpoolDeliveryResponse or GemOutcome::SpoolDeliveryWritten).
successtrue to accept the delivery and dequeue; false to stop the run.

Returns

PDCOMM_OK or PDCOMM_SPOOL_UNCONFIRMED with the mutation details. After an unconfirmed dequeue the entry is already removed: never complete it again.

Notes

  • Throws pdcomm::Error: for other statuses, for example PDCOMM_STALE_TOKEN for a foreign, stale or already completed proof.

configurePrograms

Method

Attaches the process program store and enables stream 7 program transfers.

void configurePrograms(const GemProgramOptions &options, const std::string &path = {})

Declared in: #include <pdcomm_gem.hpp>

Call once while the endpoint is stopped, after the role is configured. With an empty path the store lives in memory. Otherwise the file is opened under an exclusive lock and its bounded snapshot is loaded and validated; a missing file starts empty, and a corrupt file is never replaced. File I/O runs synchronously on the calling thread.

Parameters

NameDescription
optionsLimits built with gemProgramOptions().
pathUTF-8 file path without NUL bytes, or empty for memory only. The parent directory must exist. Program IDs are never used as paths.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE when the endpoint is not stopped, has no role, or already has a program store; PDCOMM_INVALID_ARGUMENT for invalid options or path; PDCOMM_BACKPRESSURE when another process holds the file lock; PDCOMM_IO_ERROR for file errors; PDCOMM_INVALID_DATA for a corrupt file; PDCOMM_LIMIT_EXCEEDED when the file exceeds max_serialized_bytes.

confirmProgramReply

Method

Accepts an unconfirmed installation so that its retained reply can be sent.

void confirmProgramReply(GemResult &result)

Declared in: #include <pdcomm_gem.hpp>

After respondProgram() returned PDCOMM_PROGRAM_UNCONFIRMED, call this to accept the uncertainty, then call respondProgram() again with the same arguments. It does not synchronize the file and does not send anything; call resyncPrograms() first if you need a confirmed synchronization.

Parameters

NameDescription
resultResult that is waiting for confirmation.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE when the result needs no confirmation or is not a program request of this endpoint.

confirmSpoolReply

Method

Accepts an unconfirmed spool installation so that its retained reply can be sent.

void confirmSpoolReply(GemResult &result)

Declared in: #include <pdcomm_gem.hpp>

After respondSpool() returned PDCOMM_SPOOL_UNCONFIRMED, call this, then call respondSpool() again. It neither synchronizes nor sends; the reply then reports GemSpoolDurability::Confirmed and the original persistence error stays visible.

Parameters

NameDescription
resultResult that is waiting for confirmation.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE when no confirmation is needed; PDCOMM_STALE_TOKEN for a stale result.

handle

Method

Alias of handleEvent().

GemResult handle(TcpEvent &event)

Declared in: #include <pdcomm_gem.hpp>

Parameters

NameDescription
eventEvent returned by TcpEndpoint::nextEvent() on this endpoint.

Returns

An owned result.

Notes

  • Throws pdcomm::Error: Same statuses as handleEvent().

handleEvent

Method

Processes one TCP event with the GEM layer.

GemResult handleEvent(TcpEvent &event)

Declared in: #include <pdcomm_gem.hpp>

Handle every event from tcp().nextEvent() in queue order. The event is borrowed only during the call; its TCP metadata and body stay readable afterwards. On success the event is marked as consumed by GEM. The library replies automatically to many primaries (see GemResultInfo::replySent); others wait for an explicit respond call.

Parameters

NameDescription
eventEvent returned by TcpEndpoint::nextEvent() on this endpoint.

Returns

An owned result; GemResultKind::Ignored for events unrelated to GEM.

Notes

  • Throws pdcomm::Error: PDCOMM_STALE_TOKEN when the event was already handled, comes from another endpoint, or belongs to an older connection generation; PDCOMM_BACKPRESSURE or PDCOMM_ALLOCATION_FAILED before commit, in which case the event stays retryable; PDCOMM_INVALID_STATE when no GEM role is configured; PDCOMM_INVALID_ARGUMENT for an empty event.

nextEvent

Method

Takes the next queued TCP event; forwards to TcpEndpoint::nextEvent().

TcpEvent nextEvent()

Declared in: #include <pdcomm_gem.hpp>

Returns

The next event, or an empty TcpEvent when the queue is empty.

Notes

  • Throws pdcomm::Error: with the status of pdcomm_tcp_next_event().

operator=

Method

Destroys the current native endpoint, then takes over the one owned by the source.

GemEndpoint &operator=(GemEndpoint &&) noexcept = default

Declared in: #include <pdcomm_gem.hpp>

Returns

This endpoint.

operator=

Method

Copy assignment is disabled; the endpoint exclusively owns its native handle.

GemEndpoint &operator=(const GemEndpoint &) = delete

Declared in: #include <pdcomm_gem.hpp>

poll

Method

Drives the HSMS endpoint; forwards to TcpEndpoint::poll().

size_t poll()

Declared in: #include <pdcomm_gem.hpp>

May block up to the connect timeout during an active connection attempt.

Returns

Number of internal actions taken; not the number of events queued.

Notes

  • Throws pdcomm::Error: with the status of pdcomm_tcp_poll().

program

Method

Returns a copy of the body stored under id.

SecsItem program(const SecsItem &id)

Declared in: #include <pdcomm_gem.hpp>

The ID format is part of its identity: ASCII "A" and Binary 0x41 differ.

Parameters

NameDescription
idProgram ID item (non-empty ASCII or Binary).

Returns

The body, or an empty item when no program has that ID.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE when no program store is configured; PDCOMM_INVALID_ARGUMENT for an invalid ID item.

programAt

Method

Returns a copy of one stored program in store order.

GemProgramEntry programAt(size_t index)

Declared in: #include <pdcomm_gem.hpp>

Parameters

NameDescription
indexZero-based position, less than GemProgramState::programCount.

Returns

Independently owned ID and body items.

Notes

  • Throws pdcomm::Error: PDCOMM_OUT_OF_RANGE for an invalid index; PDCOMM_INVALID_STATE when no program store is configured.

programDeleteLocal

Method

Deletes programs from the local store.

GemProgramWriteResult programDeleteLocal(const std::vector<const SecsItem *> &ids = {})

Declared in: #include <pdcomm_gem.hpp>

Allowed only while the endpoint is stopped. The selected IDs must be distinct and present.

Parameters

NameDescription
idsProgram IDs to delete; an empty vector deletes all programs. The items are borrowed during the call.

Returns

PDCOMM_OK, or PDCOMM_PROGRAM_UNCONFIRMED when the deletion was installed but the file synchronization is unconfirmed. Do not repeat it in that case.

Notes

  • Throws pdcomm::Error: for any other status, for example PDCOMM_INVALID_STATE or PDCOMM_INVALID_ARGUMENT for an unknown or duplicate ID.

programGrant

Method

Sends S7F1 Process Program Load Inquire.

PdcommTcpToken programGrant(const SecsItem &id, uint32_t length)

Declared in: #include <pdcomm_gem.hpp>

Requires a program store and the Communicating state. The reply arrives as a result with GemOutcome::ProgramGrantReceived. No grant negotiation is automatic.

Parameters

NameDescription
idProgram ID to load.
lengthProgram body size in payload bytes (LENGTH).

Returns

Token of the submitted request.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE when not communicating or no store is configured; PDCOMM_BACKPRESSURE when all 32 pending request slots are in use or a TCP event is staged; PDCOMM_LIMIT_EXCEEDED when the pending program ID budget is exhausted; PDCOMM_INVALID_ARGUMENT for an invalid ID.

programPut

Method

Writes one program to the local store.

GemProgramWriteResult programPut(const SecsItem &id, const SecsItem &body, GemProgramMode mode)

Declared in: #include <pdcomm_gem.hpp>

Allowed only while the endpoint is stopped. Validation and preparation happen before persistence and the in-memory commit; no wire message is involved.

Parameters

NameDescription
idProgram ID: non-empty ASCII or Binary, at most min(limit, 120) bytes.
bodyProgram body in A, B, I1, I2, I4, I8, U1, U2, U4 or U8 format; raw bytes and empty values are kept.
modeCreate, replace or upsert.

Returns

PDCOMM_OK, or PDCOMM_PROGRAM_UNCONFIRMED when the change was installed but the file synchronization is unconfirmed. Do not repeat the write in that case; inspect GemProgramWriteInfo::applied and GemProgramWriteInfo::durability.

Notes

  • Throws pdcomm::Error: for any other status, for example PDCOMM_INVALID_STATE when the endpoint is not stopped or has no store, PDCOMM_INVALID_ARGUMENT for an invalid ID or body or a mode conflict, PDCOMM_LIMIT_EXCEEDED for store limits, or PDCOMM_IO_ERROR. The store is unchanged on these errors.

programRequest

Method

Sends S7F5 Process Program Request.

PdcommTcpToken programRequest(const SecsItem &id)

Declared in: #include <pdcomm_gem.hpp>

The reply arrives as a result with GemOutcome::ProgramDataReceived; the received program is not installed automatically.

Parameters

NameDescription
idProgram ID to request.

Returns

Token of the submitted request.

Notes

  • Throws pdcomm::Error: Same statuses as programGrant().

programSend

Method

Sends S7F3 Process Program Send.

PdcommTcpToken programSend(const SecsItem &id, const SecsItem &body)

Declared in: #include <pdcomm_gem.hpp>

The reply arrives as a result with GemOutcome::ProgramAckReceived. A received S7F4 does not mean the peer selected or executed the program.

Parameters

NameDescription
idProgram ID.
bodyProgram body.

Returns

Token of the submitted request.

Notes

  • Throws pdcomm::Error: Same statuses as programGrant().

programState

Method

Returns counters of the process program store.

GemProgramState programState()

Declared in: #include <pdcomm_gem.hpp>

Returns

Program, byte and grant counters.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE when no program store is configured; PDCOMM_BACKPRESSURE while a TCP event is staged.

respondProgram

Method

Replies to a received process program request and returns the native status.

PdcommStatus respondProgram(GemResult &result, GemProgramMode mode, uint8_t decision = 0)

Declared in: #include <pdcomm_gem.hpp>

Use it for results with GemOutcome::ProgramReceived. For S7F1 the decision is the PPGNT; a grant activates only after S7F2 is queued. For S7F3 and S7F17 the decision is the ACKC7, and an accepted change is installed and committed before the reply is queued. S7F5 and S7F19 need decision 0. If sending fails after installation, retry with the same mode and decision: only the retained reply is sent again.

This method never throws for native statuses; check the return value.

Parameters

NameDescription
resultResult of the received request; it is updated with the reply state.
modeWrite mode used by S7F1 and S7F3.
decision0 to accept; 1 to 5 to reject with that PPGNT (S7F1) or ACKC7 (S7F3, S7F17) code.

Returns

PDCOMM_OK; PDCOMM_PROGRAM_UNCONFIRMED when the change was installed but no reply was sent (see confirmProgramReply()); PDCOMM_BACKPRESSURE or another send failure with the reply retained; PDCOMM_STALE_TOKEN for a stale, consumed or already answered request; PDCOMM_INVALID_ARGUMENT for an invalid decision.

respondSpool

Method

Replies to a received spool request and returns the native status.

PdcommStatus respondSpool(GemResult &result)

Declared in: #include <pdcomm_gem.hpp>

Use it at the equipment for results with GemOutcome::SpoolReceived (S2F43, S2F59 or S6F23). The library builds the fixed reply: S2F44 with per-stream errors, S2F60 with the current selection, or S6F24 (busy, no data, or accepted). Configuration and purge are installed before their success acknowledgement, and a transmit run starts only after an accepted S6F24 is queued. Requires a current GemEquipment::syncSpool().

This method never throws for native statuses; check the return value.

Parameters

NameDescription
resultResult of the received request.

Returns

PDCOMM_OK; PDCOMM_SPOOL_UNCONFIRMED when installed with no reply sent (see confirmSpoolReply()); PDCOMM_BACKPRESSURE or another send failure with the reply retained for retry; PDCOMM_STALE_TOKEN for a stale, consumed or already answered request.

resyncPrograms

Method

Retries synchronization of the program file's parent directory.

void resyncPrograms()

Declared in: #include <pdcomm_gem.hpp>

It never rewrites data and never confirms a retained remote reply.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE for a memory-only store or no store; PDCOMM_IO_ERROR when synchronization fails again.

resyncSpool

Method

Retries synchronization of the spool file's parent directory.

void resyncSpool()

Declared in: #include <pdcomm_gem.hpp>

It never rewrites data, sends an acknowledgement, confirms a reply or dequeues.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE for a memory-only spool or no spool; PDCOMM_IO_ERROR when synchronization fails again.

retrySpoolDequeue

Method

Retries removing an entry whose delivery was accepted but whose dequeue failed.

GemSpoolWriteResult retrySpoolDequeue()

Declared in: #include <pdcomm_gem.hpp>

Performs only persistence and dequeue, without sending again. It stays available after a reconnect, without the original delivery result.

Returns

PDCOMM_OK or PDCOMM_SPOOL_UNCONFIRMED with the mutation details.

Notes

  • Throws pdcomm::Error: for other statuses, for example PDCOMM_INVALID_STATE when no dequeue is pending.

sendNextSpool

Method

Sends the message at the head of the spool during an accepted transmit run.

PdcommTcpToken sendNextSpool()

Declared in: #include <pdcomm_gem.hpp>

Sends exactly one message; there is no automatic loop. A W-bit message uses a native pending slot and its reply arrives as GemOutcome::SpoolDeliveryResponse; a message without W-bit reports GemOutcome::SpoolDeliveryWritten after the full write. Nothing is removed until completeSpoolDelivery().

Returns

Token of the submitted message.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE when no transmit run is active or the spool is not synchronized; PDCOMM_BACKPRESSURE when a delivery is already in flight or no pending slot is free for a W-bit message; PDCOMM_OUT_OF_RANGE when the spool is empty. A failure before submission keeps the queue and stops the run.

spoolCatalogAt

Method

Returns one registered spoolable stream and function pair.

GemSpoolMessageKey spoolCatalogAt(size_t index)

Declared in: #include <pdcomm_gem.hpp>

Parameters

NameDescription
indexZero-based catalog position, less than GemSpoolState::catalogCount.

Returns

Stream and function.

Notes

  • Throws pdcomm::Error: PDCOMM_OUT_OF_RANGE for an invalid index; PDCOMM_INVALID_STATE when spooling is not configured.

spoolEntryAt

Method

Returns a copy of one stored spool entry in queue order, including its capture time.

GemSpoolEntry spoolEntryAt(size_t index)

Declared in: #include <pdcomm_gem.hpp>

The wrapper makes two native calls, pdcomm_gem_spool_entry_at() and pdcomm_gem_spool_entry_time_at(), for the same index.

Parameters

NameDescription
indexZero-based queue position, less than GemSpoolState::messageCount.

Returns

Entry metadata, owned body and capture time.

Notes

  • Throws pdcomm::Error: PDCOMM_OUT_OF_RANGE for an invalid index; PDCOMM_INVALID_STATE when spooling is not configured.

spoolSelectionAt

Method

Returns one selected stream of the current spooling selection.

GemSpoolSelection spoolSelectionAt(size_t index)

Declared in: #include <pdcomm_gem.hpp>

Parameters

NameDescription
indexZero-based position, less than GemSpoolState::selectionCount.

Returns

Stream and functions; an empty list selects every registered primary.

Notes

  • Throws pdcomm::Error: PDCOMM_OUT_OF_RANGE for an invalid index; PDCOMM_INVALID_STATE when spooling is not configured.

spoolState

Method

Returns the state of the equipment spool.

GemSpoolState spoolState()

Declared in: #include <pdcomm_gem.hpp>

Returns

Counters, policy and flags. synchronized is false while a GemEquipment::syncSpool() call is required.

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE on a host or when spooling is not configured.

start

Method

Starts the HSMS endpoint; forwards to TcpEndpoint::start().

void start()

Declared in: #include <pdcomm_gem.hpp>

Configure the GEM role and every store before starting.

Notes

  • Throws pdcomm::Error: with the status of pdcomm_tcp_start().

state

Method

Returns the current GEM state.

GemState state()

Declared in: #include <pdcomm_gem.hpp>

Synchronizes the GEM state with the HSMS session first, so a new connection generation or a lost selection is visible immediately.

Returns

Role, communication and control states, identity and pending counts.

Notes

  • Throws pdcomm::Error: PDCOMM_BACKPRESSURE while a TCP event is staged; PDCOMM_INVALID_STATE when no GEM role is configured.

stop

Method

Stops the HSMS endpoint; forwards to TcpEndpoint::stop().

void stop()

Declared in: #include <pdcomm_gem.hpp>

For a graceful close, keep polling and draining events until the TCP state reports closed before destroying the endpoint.

Notes

  • Throws pdcomm::Error: with the status of pdcomm_tcp_stop().

stopSpoolTransmit

Method

Ends the current transmit run.

void stopSpoolTransmit()

Declared in: #include <pdcomm_gem.hpp>

Notes

  • Throws pdcomm::Error: PDCOMM_INVALID_STATE while a delivery is in flight or an accepted dequeue is pending.

tcp

Method

Returns the underlying HSMS endpoint.

TcpEndpoint &tcp() noexcept

Declared in: #include <pdcomm_gem.hpp>

Use it for TCP-level calls such as TcpEndpoint::nextEvent(), TcpEndpoint::state(), TcpEndpoint::localAddress(), TcpEndpoint::linktest() and TcpEndpoint::reply().

Returns

The owned TcpEndpoint; valid as long as this object lives.

tcp

Method

Returns the underlying HSMS endpoint for read-only calls.

const TcpEndpoint &tcp() const noexcept

Declared in: #include <pdcomm_gem.hpp>

Returns

The owned TcpEndpoint; valid as long as this object lives.