Engine Channel#

class EngineChannel#

The command queue plus the gate that decides whether new work may still enter it.

Held by shared_ptr by the engine and by every handle it hands out, which is what makes a handle that outlives its engine safe: cancelling through a dead engine reaches this object rather than a destroyed one. Commands posted after the engine is gone are simply never drained, and that costs nothing because the engine terminates every outstanding request before it goes away.

Admission is guarded by a mutex rather than an atomic flag, and that is the point of the class. Checking a flag and then pushing are two steps, so a submit that reads the gate as open can be descheduled, have the engine shut down and sweep the queue underneath it, and then publish a request that no actor will ever run — stranding its caller forever. Closing the gate under the same mutex the push holds makes “accepted” and “will be drained” the same decision. The lock is held for one queue push, is never taken by the actor, and so never serialises execution.

Public Functions

inline explicit EngineChannel(int32_t commandQueueCapacity)#
EngineChannel(EngineChannel const&) = delete#
EngineChannel &operator=(EngineChannel const&) = delete#
inline bool postSubmit(std::unique_ptr<EngineCommand> command)#

Any thread: offer a request. Fails if admission is closed or the queue is full.

inline bool post(std::unique_ptr<EngineCommand> command)#

Any thread: post a command that stops work rather than creating it.

Deliberately not gated on admission. A cancel or shutdown arriving after the gate closed is exactly the case that still needs delivering, and the actor drops anything it can no longer act on.

inline void closeAdmission()#

Stop accepting submissions. Once this returns, no push of a submit can still be in flight, so a sweep of the queue afterwards is final.

inline bool accepting() const#
inline std::unique_ptr<EngineCommand> pop()#

Actor thread only.

inline bool hasPending() const noexcept#
inline int32_t capacity() const noexcept#

The ring’s real slot count (the requested capacity rounded up), so a drain budget sized by it empties a full queue in one pass.

inline void registerRecord(
std::shared_ptr<RequestRecord> const &record
)#

Any thread: make record cancellable by id for as long as it is live. submit() registers before posting; the actor forgets when the outcome is published.

inline void forgetRecord(RequestId id)#
inline bool cancelRecord(RequestId id) noexcept#

Any thread: plant the cancel flag on a live request by id, exactly as RequestHandle::cancel() does through its own record. Lossless &#8212; no queue is involved, so overload cannot drop it &#8212; and a no-op for an id that is unknown or already retired.

Returns:

whether a live record was found.