diff --git a/score/time_daemon/docs/detailed_design/index.rst b/score/time_daemon/docs/detailed_design/index.rst
index 21292f0d..3c8d6762 100644
--- a/score/time_daemon/docs/detailed_design/index.rst
+++ b/score/time_daemon/docs/detailed_design/index.rst
@@ -126,688 +126,377 @@ The data and control flow between units is presented in the following diagram:
-On this view you could see several "workers" scopes:
+On this view you can see several execution scopes:
-1. PTP retrieving scope
-2. PTPTimeInfo handling scope
-3. PTPTimeInfo receiving on Application side scope
+1. **PTP retrieving scope** — retrieves latest PTP data and publishes to ``raw_ptp_data`` topic
+2. **PTPTimeInfo handling scope** — validates time data and publishes to ``verified_ptp_data`` topic
+3. **PTPTimeInfo receiving scope** — propagates qualified time to client applications
-Each control flow is implemented with the dedicated thread or process and is independent form another ones.
+Each control flow is implemented with a dedicated thread or process and is independent from the others.
-Control flows
-^^^^^^^^^^^^^
-
-PTP retrieving scope
-''''''''''''''''''''
-
-This control flow is responsible for the:
-
-1. retrieve the latest information from the ptp stack and
-2. provide it to the ``PTPTimeInfo handling`` control flow
-
-PTPTimeInfo handling scope
-'''''''''''''''''''''''''''
+Data Types or Events
+^^^^^^^^^^^^^^^^^^^^^
-This control flow is responsible for the:
+Main data exchanged between units via MessageBroker topics:
-1. Validate the time information, provided by the ``PTP retrieving`` workflow and
-2. publish it to the ``Applications`` via some IPC
+- ``PtpTimeInfo`` — internal time snapshot struct containing sync data, peer delay, status flags, and timestamps
-PTPTimeInfo receiving on Application side scope
-''''''''''''''''''''''''''''''''''''''''''''''''
-
-This control flow is responsible for the:
-
-1. Propagate the time information from the ``PTPTimeInfo handling`` to the business logic of the applications.
-
-Data types or events
-^^^^^^^^^^^^^^^^^^^^
-
-There are also several data types, which components are communicating to each other:
+Topic names:
.. _raw_ptp_data:
-Raw ptp data
-''''''''''''
+.. rubric:: raw_ptp_data
-``raw_ptp_data`` is the data, which is provided by ``PTPMachine`` component and is just the raw data from ptp stack. is handled in the "PTP retrieving scope"
+Raw PTP snapshot from ``PtpMachine``; published to ``ControlFlowDivider`` for thread separation.
.. _input_ptp_data:
-Input ptp data
-''''''''''''''
+.. rubric:: input_ptp_data
-``input_ptp_data`` is the same data as :ref:`raw_ptp_data` but which is handled already in "PTPTimeInfo handling scope"
+Same data as :ref:`raw_ptp_data` but republished at consistent rate by ``ControlFlowDivider``; consumed by ``VerificationMachine``.
.. _verified_ptp_data:
-Verified ptp data
-'''''''''''''''''
+.. rubric:: verified_ptp_data
-``verified_ptp_data`` is the :ref:`input_ptp_data` which was verified according to the business logic and updated accordingly. This data should be published to the Applications.
+Validated and qualified time snapshot from ``VerificationMachine``; includes sync status, timeout flags, time jump detection; published to ``PublisherImpl``.
-Units within Time Daemon
--------------------------
+Units within the Component
+---------------------------
The following units comprise TimeDaemon's internal implementation:
-Application Unit
-~~~~~~~~~~~~~~~~
+- ``TimeDaemon`` — main entry point orchestrating lifecycle and initialization
+- ``MessageBroker`` — publish-subscribe hub for decoupled inter-unit communication
+- ``ControlFlowDivider`` — separates execution threads to prevent blocking
+- ``PtpMachine`` — retrieves raw time data from PTP stack
+- ``ShmPtpEngine`` — reads gPTP data from TimeSlave shared memory channel
+- ``VerificationMachine`` — validates and qualifies time data
+- ``PublisherImpl`` — publishes qualified time snapshots via shared memory
+- ``ReceiverImpl`` — receives time data from shared memory
-The ``Application`` component is the main entry point for the ``TimeDaemon``. It is responsible for orchestrating the overall lifecycle and initialization of all daemon components.
+Per-Unit Diagrams
+~~~~~~~~~~~~~~~~~
-The ``TimebaseHandler`` component is an timebase-specific logic implementation. There might be several handlers available in the ``Application`` per amount of timebases supported. This separation allows for different timebase implementations while maintaining a consistent application structure.
+Application
+^^^^^^^^^^^
-Implementation Requirements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The ``Application`` component is the main entry point for TimeDaemon, orchestrating lifecycle and initialization of all daemon components.
-The ``Application`` has the following requirements:
+The ``TimebaseHandler`` component implements timebase-specific logic. Multiple handlers may exist per supported timebase count, allowing different timebase implementations while maintaining consistent application structure.
-- The ``Application`` shall implement the ``Initialize()`` method to create and initialize all daemon components
-- The ``Application`` shall implement the ``Run()`` method to start all components and wait for termination
-- The ``Application`` shall connect components to the ``MessageBroker`` by setting up all required subscriptions during initialization stage
-- The ``Application`` shall support extension for different timebases.
+During initialization, the ``Application`` uses a factory pattern to create components in specific order:
-Class view
-^^^^^^^^^^
+- Create ``MessageBroker`` first (other components depend on it)
+- Create ProactiveMachines (``PtpMachine``, ``ControlFlowDivider``) that drive system behavior, then initialize and wire subscriptions
+- Create ReactiveMachines (``VerificationMachine``, ``IPCMachine``) that respond to events, then initialize and wire subscriptions
-The Class Diagram is presented below:
+During execution, ProactiveMachines start in correct order. On termination, they stop in reverse order.
+
+Class diagram:
.. raw:: html
.. uml:: _assets/app/app_class.puml
- :alt: Class Diagram
+ :alt: Application class diagram
.. raw:: html
-Initialization flow
-^^^^^^^^^^^^^^^^^^^
-
-During initialization, the ``Application`` uses the ``MachineFactory`` to create, configure and subscribe all components in a specific order:
-
-- Create the ``MessageBroker`` first, as other components depend on it
-- Create ProactiveMachines (``PtpMachine``, ``ControlFlowDivider``) that drive system behavior
-
- - Initialize each component
- - Set up MessageBroker subscriptions to component notifications
- - Set up component subscriptions to MessageBroker topics
-
-- Create ReactiveMachines (``VerificationMachine``, ``IPCMachine``) that respond to events
-
- - Initialize each component
- - Set up MessageBroker subscriptions to component notifications
- - Set up component subscriptions to MessageBroker topics
-
-The initialization workflow is represented in the following sequence diagram:
+Initialization sequence showing component creation order and MessageBroker subscription wiring:
.. raw:: html
.. uml:: _assets/app/app_init_seq.puml
- :alt: Initialization workflow
+ :alt: Application initialization sequence
.. raw:: html
-Execution and shutdown flow
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-During execution, the ``Application``:
-
-- Starts all ``ProactiveMachines`` in the correct order
-- Monitors the stop token for termination requests
-- When termination is requested, stops all ``ProactiveMachines`` in reverse order
-
-The execution and shutdown workflow is represented in the following sequence diagram:
+Runtime workflow showing ProactiveMachine startup and shutdown coordination:
.. raw:: html
.. uml:: _assets/app/app_workflow_seq.puml
- :alt: Execution workflow
+ :alt: Application workflow sequence
.. raw:: html
+MessageBroker
+^^^^^^^^^^^^^
-
-Message Broker Unit
-~~~~~~~~~~~~~~~~~~~
-
-The ``Message Broker`` component is the central communication hub that implements the Publish-Subscribe pattern within the ``TimeDaemon``. It enables decoupled communication between components by managing topics and distributing messages to interested subscribers.
-
-The component maintains a registry of topics and their subscribers, delivering messages to all registered subscribers when a component publishes to a topic. This decoupling allows components to evolve independently without direct dependencies on each other.
-
-Implementation Requirements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``Message Broker`` has the following requirements:
-
-- The ``Message Broker`` shall maintain a registry of topics and their subscribers
-- The ``Message Broker`` shall allow components to subscribe to topics of interest
-- The ``Message Broker`` shall distribute messages to all subscribers when a topic is published to
-
-Class view
-^^^^^^^^^^
-
-The Class Diagram is presented below:
+Class diagram:
.. raw:: html
.. uml:: _assets/msg_broker/msg_broker_class.puml
- :alt: Class Diagram
+ :alt: MessageBroker class diagram
.. raw:: html
-Initialization flow
-^^^^^^^^^^^^^^^^^^^
-
-During initialization, all machine objects, see ``BaseMachine``, the ``Application`` component needs to subscribe machines to ``Message Broker`` to the topics of interest.
-
-The initialization workflow is represented in the following sequence diagram:
+Initialization workflow:
.. raw:: html
.. uml:: _assets/msg_broker/msg_broker_init_seq.puml
- :alt: Initialization workflow
+ :alt: MessageBroker initialization
.. raw:: html
-Message flow
-^^^^^^^^^^^^
-
-The message flow through the ``Message Broker`` is represented in the following sequence diagram:
+Message flow through MessageBroker showing topic distribution to multiple subscribers:
.. raw:: html
.. uml:: _assets/msg_broker/msg_broker_workflow_seq.puml
- :alt: Message DiagramFlow
+ :alt: MessageBroker message distribution
.. raw:: html
-Concurrency aspects
-^^^^^^^^^^^^^^^^^^^
-
-The ``Message Broker`` doesn't provide any synchronization between the publish-callback invoking processes.
-Moreover, the callback invoke will happened in the scope of the thread, where the ``publish`` method is called.
-To separate the control flows, the ``ControlFlowDivider`` shall be used.
-
-Scalability
-^^^^^^^^^^^
-
-The ``Message Broker`` can be extended to support configuration-driven subscriptions, where topic relationships are defined in configuration files rather than hardcoded.
+ControlFlowDivider
+^^^^^^^^^^^^^^^^^^
-
-
-ControlFlowDivider Unit
-~~~~~~~~~~~~~~~~~~~~~~~
-
-The ``ControlFlowDivider`` component is responsible for separating control (execution) flows within the ``TimeDaemon`` and providing the execution control flow for the data processing. It contains dedicated threads where data is published to the ``Message Broker``, ensuring that blocking operations in one component do not affect the execution of other components and data missing is not affecting the data analysis in processing pipeline.
-
-This component acts as a crucial intermediary that maintains the responsiveness of the system by decoupling the execution contexts of different operations, particularly between the PTP data retrieval and the time data processing pipelines.
-
-Implementation Requirements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``ControlFlowDivider`` has the following requirements:
-
-- The ``ControlFlowDivider`` shall provide separate execution threads for different control flows
-- The ``ControlFlowDivider`` shall isolate components from execution time variations in other components
-- The ``ControlFlowDivider`` shall maintain consistent data publishing rates to the subscribers
-- The ``ControlFlowDivider`` shall push the last received data to the subscribers if there is no new data for some time with the predefined rate, to avoid data missing in the processing pipeline
-- The ``ControlFlowDivider`` shall enable periodic processing of the pipeline through consistent event generation
-- The ``ControlFlowDivider`` shall buffer incoming data from fast producers
-
-Class view
-^^^^^^^^^^
-
-The Class Diagram is presented below:
+Class diagram:
.. raw:: html
.. uml:: _assets/ctrlflow/ctrlflow_class.puml
- :alt: Class Diagram
+ :alt: ControlFlowDivider class diagram
.. raw:: html
-Initialization flow
-^^^^^^^^^^^^^^^^^^^
-
-During initialization, the ``ControlFlowDivider`` performs the following steps:
-
-- Initialize internal data structures (queue, mutex, condition variable)
-- Create a worker thread to process data independently
-- Start the worker thread which enters a waiting state
-
-The initialization workflow is represented in the following sequence diagram:
+Initialization workflow:
.. raw:: html
.. uml:: _assets/ctrlflow/ctrlflow_init_seq.puml
- :alt: Initialization workflow
+ :alt: ControlFlowDivider initialization
.. raw:: html
-Message flow
-^^^^^^^^^^^^
-
-When the ``ControlFlowDivider`` receives new data from the ``PTP Machine`` via the ``Message Broker``, it processes it through the following workflow:
-
-1. The ``Message Broker`` executes the onNewData callback and provides the new data
-2. The data is placed in a thread-safe queue and exists from the callback
-3. The worker thread wakes up, retrieves the data from the queue and
-4. The worker thread publishes the retrieved data to the :ref:`input_ptp_data` topic
-5. if there was no data for some timeout, the worker shall published the empty data to the :ref:`input_ptp_data` topic.
-
-This separation of control flows ensures that slow or blocking operations in the PTP stack communication do not affect the responsiveness of time data processing in the ``TimeDaemon``.
-
-The execution workflow is represented in the following sequence diagram:
+Thread separation and periodic republishing workflow:
.. raw:: html
.. uml:: _assets/ctrlflow/ctrlflow_workflow_seq.puml
- :alt: Execution workflow
+ :alt: ControlFlowDivider workflow
.. raw:: html
-
-
-PTP Machine Unit
-~~~~~~~~~~~~~~~~
-
-The ``PTP Machine`` component shall retrieve all needed information from the ptp stack (ex ``ptpd``) and provide it to the ``Message Broker`` for routing.
-All communication with the ptp stack ight use ``devctl`` calls, which take some time, thus these calls shall be done in the dedicated thread.
-
-Implementation Requirements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``PTP Machine`` has the following requirements:
-
-- The ``PTP Machine`` shall retrieve the latest time information from the PTP stack (e.g., ``ptpd``)
-- The ``PTP Machine`` shall publish retrieved time information to the ``Message Broker`` using the defined topic
-- The ``PTP Machine`` shall format data according to the ``PtpTimeInfo`` structure required by downstream components
-- The ``PTP Machine`` shall retrieve time information at a consistent rate to maintain time synchronization
-- The ``PTP Machine`` shall maintain consistent publishing rates for time data even when experiencing delays in PTP stack communication.
-- The ``PTP Machine`` shall support exchangeability with different PTP stack implementations
-
-Class view
+PTPMachine
^^^^^^^^^^
-The Class Diagram is presented below.
+Class diagram:
.. raw:: html
.. uml:: _assets/ptp_machine/ptp_machine_class.puml
- :alt: Class Diagram
+ :alt: PTPMachine class diagram
.. raw:: html
-As long as it wraps the particular communication with the ptp stack, the implementations should be easily exchangeable with another one in case of stack change.
-
-Component initialization
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-During initialization the ``PTP Machine`` shall initialize the ptp stack to be able to communicate with it.
-
-The initialization workflow is described below.
+Initialization workflow:
.. raw:: html
.. uml:: _assets/ptp_machine/ptp_machine_init_seq.puml
- :alt: Initialization workflow
+ :alt: PTPMachine initialization
.. raw:: html
-Publish new data
-^^^^^^^^^^^^^^^^
-
-After ``PTP Machine`` collects new data from the ptp stack, the component shall publish it to the ``Message Broker`` as :ref:`raw_ptp_data`.
-
-The publish workflow is described below.
+PTP data retrieval cycle from shared memory:
.. raw:: html
.. uml:: _assets/ptp_machine/ptp_machine_get_new_data_seq.puml
- :alt: Publish workflow
+ :alt: PTPMachine data retrieval
.. raw:: html
-ShmPTPEngine Unit
-~~~~~~~~~~~~~~~~~
-
-The ``ShmPTPEngine`` component (in ``score::td::details``) is a ``PTP Machine`` implementation that reads ``GptpIpcData`` from the shared memory channel written by TimeSlave and converts it into the ``PtpTimeInfo`` structure expected by the TimeDaemon pipeline.
-
-It is instantiated as ``GPTPShmMachine`` — a type alias for ``PTPMachine`` — which connects ``ShmPTPEngine`` to the TimeDaemon's internal ``MessageBroker``.
-
-Implementation Requirements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``ShmPTPEngine`` has the following requirements:
-
-- The ``ShmPTPEngine`` shall call ``GptpIpcReceiver::Init(ipc_name)`` during ``Initialize()`` to open the shared memory channel
-- The ``ShmPTPEngine`` shall call ``GptpIpcReceiver::Receive()`` in ``ReadPTPSnapshot()`` to fetch the latest ``GptpIpcData``
-- The ``ShmPTPEngine`` shall map all fields of ``GptpIpcData`` to the corresponding fields of ``PtpTimeInfo`` (status flags, Sync/FollowUp data, peer-delay data, time references)
-- The ``ShmPTPEngine`` shall call ``GptpIpcReceiver::Close()`` during ``Deinitialize()``
-- The ``ShmPTPEngine`` shall be instantiatable with a configurable IPC channel name (default: ``/gptp_ptp_info``)
-
-Class View
-^^^^^^^^^^
+ShmPTPEngine
+^^^^^^^^^^^^
-The Class Diagram is presented below:
+Class diagram:
.. raw:: html
.. uml:: _assets/shm_ptp_engine/shm_ptp_engine_class.puml
- :alt: Class Diagram
+ :alt: ShmPTPEngine class diagram
.. raw:: html
-Initialization
-^^^^^^^^^^^^^^
-
-During initialization the ``ShmPTPEngine`` shall open the shared memory channel to be able to read from it.
-
-The initialization workflow is represented in the following sequence diagram:
+Initialization workflow:
.. raw:: html
.. uml:: _assets/shm_ptp_engine/shm_ptp_engine_init_seq.puml
- :alt: Initialization workflow
+ :alt: ShmPTPEngine initialization
.. raw:: html
-Read PTP Snapshot
-^^^^^^^^^^^^^^^^^
-
-After ``ShmPTPEngine`` reads the latest ``GptpIpcData`` from shared memory, it maps it to ``PtpTimeInfo`` and publishes via the ``MessageBroker``.
-
-The periodic read and publish workflow is described below:
+Shared memory read from TimeSlave gPTP publisher:
.. raw:: html
.. uml:: _assets/shm_ptp_engine/shm_ptp_engine_read_seq.puml
- :alt: Periodic read and publish workflow
+ :alt: ShmPTPEngine read sequence
.. raw:: html
-Data Mapping
-^^^^^^^^^^^^
-
-``ShmPTPEngine::ReadPTPSnapshot()`` performs a field-by-field mapping from ``GptpIpcData`` to ``PtpTimeInfo``:
-
-.. list-table:: GptpIpcData → PtpTimeInfo Mapping
- :header-rows: 1
- :widths: 50 50
-
- * - ``GptpIpcData`` field
- - ``PtpTimeInfo`` field
- * - ``ptp_assumed_time``
- - ``ptp_assumed_time``
- * - ``local_time``
- - ``local_time`` (wrapped in ``ReferenceClock::time_point``)
- * - ``rate_deviation``
- - ``rate_deviation``
- * - ``status.is_synchronized``
- - ``status.is_synchronized``
- * - ``status.is_timeout``
- - ``status.is_timeout``
- * - ``status.is_time_jump_future``
- - ``status.is_time_jump_future``
- * - ``status.is_time_jump_past``
- - ``status.is_time_jump_past``
- * - ``status.is_correct``
- - ``status.is_correct``
- * - ``sync_fup_data.*`` (9 fields)
- - ``sync_fup_data.*`` (direct copy)
- * - ``pdelay_data.*`` (12 fields)
- - ``pdelay_data.*`` (direct copy)
-
-Factory
-^^^^^^^
-
-``CreateGPTPShmMachine(name, ipc_name)`` is a convenience factory function in ``score::td`` that creates a configured ``GPTPShmMachine`` (``shared_ptr``) backed by ``ShmPTPEngine``:
-
-.. code-block:: cpp
-
- auto machine = CreateGPTPShmMachine("shm", "/gptp_ptp_info");
-
-
-
-Verification Machine Unit
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The ``Verification Machine`` component is responsible for validating and qualifying the time information received from the ``PTP Machine``. It applies various validation rules to ensure the time data meets quality requirements before distribution to applications.
-
-The component implements a pipeline pattern where each stage performs a specific validation and adds appropriate qualifiers to the time data. This modular design allows for easy extension with additional validation steps.
-
-Implementation Requirements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``Verification Machine`` has the following requirements:
-
-- The ``Verification Machine`` shall validate and qualify time information received from the PTP Machine
-- The ``Verification Machine`` shall validate if the time base is synchronized state
-- The ``Verification Machine`` shall validate if the time base is in timeout state
-- The ``Verification Machine`` shall validate timestamp for time jumps based on local clock
-- The ``Verification Machine`` shall subscribe to the :ref:`input_ptp_data` topic via the ``Message Broker``
-- The ``Verification Machine`` shall publish verified time data to the ``Message Broker`` using the :ref:`verified_ptp_data` topic
-- The ``Verification Machine`` shall support extensibility to add new validation stages in the pipeline
-
-Class view
-^^^^^^^^^^
+VerificationMachine
+^^^^^^^^^^^^^^^^^^^
-The Class Diagram is presented below.
+Class diagram:
.. raw:: html
.. uml:: _assets/ver_machine/ver_class.puml
- :alt: Class Diagram
+ :alt: VerificationMachine class diagram
.. raw:: html
-Component initialization
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-During initialization, the ``Verification Machine`` performs the following steps:
-
-1. Set up the validation pipeline by creating and connecting validation stages
-
-The component shall be subscribed by the ``Application`` to the :ref:`input_ptp_data` topic of the ``MessageBroker``
-
-The initialization workflow is represented in the following sequence diagram:
+Initialization workflow:
.. raw:: html
.. uml:: _assets/ver_machine/ver_init_seq.puml
- :alt: Initialization workflow
+ :alt: VerificationMachine initialization
.. raw:: html
-Data verification workflow
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-When the ``Verification Machine`` receives new PTP data, it processes it through the validation pipeline:
+Time data validation stages (sync check, timeout, jump detection):
.. raw:: html
.. uml:: _assets/ver_machine/ver_verification_seq.puml
- :alt: Validation pipeline
+ :alt: VerificationMachine pipeline
.. raw:: html
+IPC Machine
+^^^^^^^^^^^
-
-IPC Machine Unit
-~~~~~~~~~~~~~~~~
-
-The ``IPC Machine`` component shall get the :ref:`verified_ptp_data` from the ``Verification Machine`` and provide it to the ``VehicleClock`` backend (see :doc:`score::time — Unified Clock Interface <../../time/index>`) through a custom shared memory channel.
-
-The component provides two sub components: publisher and receiver to be deployed on the TimeDaemon and Application sides accordingly.
-
-Implementation Requirements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``IPC Machine`` has the following requirements:
-
-- The ``IPC Machine`` shall provide verified time data to the ``VehicleClock`` backend component through a custom shared memory channel
-- The ``IPC Machine`` shall create and initialize the IPC
-- The ``IPC Machine`` shall support multiple client applications accessing the same time data
-- The ``IPC Machine`` shall subscribe to the :ref:`verified_ptp_data` topic via the ``Message Broker``
-
-Class view
-^^^^^^^^^^
-
-The Class Diagram is presented below.
+Class diagram:
.. raw:: html
.. uml:: _assets/ipc/ipc_class.puml
- :alt: Class Diagram
+ :alt: IPC class diagram
.. raw:: html
-Component initialization
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Initialization is divided to two parts:
-
-1. Initialization on the TimeDaemon side
-2. Initialization on the Application side
-
-Important thing, the shared memory IPC publisher shall be created and offered by the ``TimeDaemon`` before the Application side subscriber can connect. The Application shall retry until the service is found.
-
-The main workflow is described below.
+Initialization workflow:
.. raw:: html
.. uml:: _assets/ipc/ipc_init_seq.puml
- :alt: Main workflow
+ :alt: IPC initialization
.. raw:: html
-The component shall be subscribed during initialization by the ``Application`` on the :ref:`verified_ptp_data` updates from the ``Message Broker``
-
-Publish new data
-^^^^^^^^^^^^^^^^
-
-When ``IPC Machine`` receives the new :ref:`verified_ptp_data` from Message Broker, it shall serialize data and write it to shared memory.
-
-As long as there are different use cases by using it, like:
-
-1. Get current Vehicle time
-2. Get data for diagnostics
-
-All ``PtpTimeInfo`` data (or almost all) shall be published to the subscribed applications.
-
-The publish workflow is described below.
+Qualified time snapshot publishing to client shared memory:
.. raw:: html
.. uml:: _assets/ipc/ipc_publish_seq.puml
- :alt: Publish workflow
+ :alt: IPC publish sequence
.. raw:: html
-Receive data
-^^^^^^^^^^^^
-
-From Application side the receiver shall read from shared memory via the IPC receiver component and provide the data to the caller.
-
-The receive workflow is described below.
+Client-side receive from TimeDaemon shared memory channel:
.. raw:: html
.. uml:: _assets/ipc/ipc_receive_seq.puml
- :alt: Receive workflow
+ :alt: IPC receive sequence
.. raw:: html
-
-
Logging configuration
~~~~~~~~~~~~~~~~~~~~~
diff --git a/score/time_daemon/src/application/time_daemon.h b/score/time_daemon/src/application/time_daemon.h
index 91108263..5e3ec474 100644
--- a/score/time_daemon/src/application/time_daemon.h
+++ b/score/time_daemon/src/application/time_daemon.h
@@ -22,6 +22,16 @@ namespace score
namespace td
{
+/// @brief Main entry point for the TimeDaemon process. Orchestrates the lifecycle
+/// of all daemon components.
+///
+/// Retrieves Vehicle Time from the PTP slave daemon, verifies and validates
+/// timepoints, and distributes time to clients via shared memory. Uses
+/// MachineFactory to create components and wire pub/sub relationships via
+/// MessageBroker.
+///
+/// @see TimebaseHandler
+/// @see score::mw::lifecycle::Application
class TimeDaemon final : public score::mw::lifecycle::Application
{
public:
@@ -33,7 +43,26 @@ class TimeDaemon final : public score::mw::lifecycle::Application
TimeDaemon& operator=(TimeDaemon&&) & noexcept = delete;
TimeDaemon& operator=(const TimeDaemon&) & noexcept = delete;
+ /// @brief Creates the MessageBroker and all machine components, and sets up subscriptions.
+ ///
+ /// Creates components in dependency order:
+ /// 1. MessageBroker
+ /// 2. ProactiveMachines: PtpMachine, ControlFlowDivider
+ /// 3. ReactiveMachines: VerificationMachine, IPCMachine
+ ///
+ /// Wires all pub/sub relationships via MessageBroker topic configuration.
+ ///
+ /// @param context Application context from the middleware.
+ /// @return 0 on success, non-zero on failure.
std::int32_t Initialize(const score::mw::lifecycle::ApplicationContext& context) override;
+
+ /// @brief Starts the ProactiveMachines and monitors the stop token.
+ ///
+ /// Execution loop monitors stop_token. On termination request, stops all
+ /// ProactiveMachines in reverse order of startup for clean shutdown.
+ ///
+ /// @param token Stop token for graceful shutdown.
+ /// @return 0 on success, non-zero on failure.
std::int32_t Run(const score::cpp::stop_token& token) override;
private:
diff --git a/score/time_daemon/src/control_flow_divider/core/control_flow_divider.h b/score/time_daemon/src/control_flow_divider/core/control_flow_divider.h
index b6e1a9e3..efaef775 100644
--- a/score/time_daemon/src/control_flow_divider/core/control_flow_divider.h
+++ b/score/time_daemon/src/control_flow_divider/core/control_flow_divider.h
@@ -32,29 +32,28 @@ namespace score
namespace td
{
-/**
- * @brief Component responsible for decoupling data flow and timing within VehicleTimeDaemon.
- *
- * The ControlFlowDivider acts as a buffer between data producers and consumers, ensuring
- * that timing-sensitive operations are not affected by blocking operations in downstream
- * components. It maintains consistent data publishing rates by using a dedicated thread
- * and internal buffering. When new data arrives, it processes all available data immediately.
- * If no new data arrives within the specified timeout, it republishes the last known data
- * to maintain consistent output timing.
- *
- * @tparam DataType The type of data being processed (e.g., PtpTimeInfo)
- * @tparam BufferSize The size of the internal circular buffer for storing incoming data
- */
+/// @brief Component responsible for decoupling data flow and timing within VehicleTimeDaemon.
+///
+/// The ControlFlowDivider acts as a buffer between data producers and consumers, ensuring
+/// that timing-sensitive operations are not affected by blocking operations in downstream
+/// components. It maintains consistent data publishing rates by using a dedicated thread
+/// and internal buffering. When new data arrives, it processes all available data immediately.
+/// If no new data arrives within the specified timeout, it republishes the last known data
+/// to maintain consistent output timing.
+///
+/// Thread safety: @c OnMessage() called from MessageBroker thread; @c OnEvent() / @c OnTimeout()
+/// called from worker thread. Synchronized via @c data_buffer_mutex_.
+///
+/// @tparam DataType The type of data being processed (e.g. PtpTimeInfo).
+/// @tparam BufferSize The size of the internal circular buffer for incoming data.
template
class ControlFlowDivider final : public EventDrivenMachine, public Consumer, public Producer
{
public:
- /**
- * @brief Constructs a ControlFlowDivider with specified timeout.
- *
- * @param name The name of this control flow divider instance
- * @param timeout Maximum time to wait for new data before republishing the last known data
- */
+ /// @brief Constructs a ControlFlowDivider with the specified timeout.
+ ///
+ /// @param name The name of this control flow divider instance.
+ /// @param timeout Maximum time to wait for new data before republishing the last known data.
explicit ControlFlowDivider(const std::string& name, std::chrono::milliseconds timeout);
~ControlFlowDivider() override = default;
@@ -64,50 +63,48 @@ class ControlFlowDivider final : public EventDrivenMachine, public Consumer callback) override;
- /**
- * @brief Receives new data and queues it for processing.
- *
- * This method receives incoming data, stores it in the internal buffer,
- * and triggers the event-driven processing mechanism to handle the data.
- * The operation is thread-safe and non-blocking.
- *
- * @param data The data to be queued for processing
- */
+ /// @brief Receives new data and queues it for asynchronous processing.
+ ///
+ /// This method receives incoming data, stores it in the internal buffer,
+ /// and triggers the event-driven processing mechanism to handle the data.
+ /// The operation is thread-safe and non-blocking.
+ ///
+ /// @param data The data to be queued for processing.
void OnMessage(DataType data) override;
protected:
+ /// @brief Drains the circular buffer and publishes each queued item in FIFO order.
+ ///
+ /// Called by the EventDrivenMachine worker thread when @c OnMessage() triggers
+ /// an event. Acquires @c data_buffer_mutex_ and publishes all pending items.
void OnEvent() noexcept override;
+ /// @brief Republishes the last known data when no new data has arrived within the timeout.
+ ///
+ /// Called by the EventDrivenMachine worker thread on timeout expiry. Publishes
+ /// the cached @c last_data_ to preserve a consistent output cadence even when
+ /// the upstream data flow stalls.
void OnTimeout() noexcept override;
private:
- /**
- * @brief Publishes data to the Message Broker.
- *
- * @param data The data to be published
- */
+ /// @brief Publishes data to the MessageBroker via the registered callback.
+ ///
+ /// @param data The data to be published.
void Publish(const DataType& data) override;
std::mutex data_buffer_mutex_;
score::cpp::circular_buffer data_buffer_;
- /** @brief Callback function for publishing data */
+ /// @brief Callback function for publishing data
std::function publish_callback_;
DataType last_data_;
diff --git a/score/time_daemon/src/ipc/core/publisher_impl.h b/score/time_daemon/src/ipc/core/publisher_impl.h
index 40ed78ed..e76efe73 100644
--- a/score/time_daemon/src/ipc/core/publisher_impl.h
+++ b/score/time_daemon/src/ipc/core/publisher_impl.h
@@ -25,13 +25,33 @@ namespace score
namespace td
{
+/// @brief IPC Machine publisher component that distributes verified time data
+/// to client applications via shared memory.
///
-/// \brief Publisher class to publish data through ipc to Client
+/// Receives verified @c PtpTimeInfo from the MessageBroker (via the
+/// @c verified_ptp_data topic), converts it to the target IPC format (e.g.
+/// @c svt::TimeBaseSnapshot), and writes it to a custom shared memory channel
+/// for consumption by VehicleClock backend clients.
///
+/// Runs in reactive mode: @c OnMessage() is called by MessageBroker when new
+/// @c verified_ptp_data arrives. @c SharedMemoryHandler::Send() is thread-safe
+/// for a single writer (only one thread may call @c OnMessage() concurrently);
+/// multiple readers on the application side can access the segment concurrently.
+///
+/// @tparam DataType Internal data type (e.g. PtpTimeInfo from MessageBroker).
+/// @tparam IpcDataType Shared memory IPC data type (e.g. svt::TimeBaseSnapshot).
+///
+/// @see SvtPublisher Type alias for PublisherImpl
+/// @see SharedMemoryHandler Shared memory management implementation
+/// @see ConvertToIpcData Data conversion function
template
class PublisherImpl : public ReactiveMachine, public Consumer
{
public:
+ /// @brief Constructs the IPC publisher with a shared memory path.
+ ///
+ /// @param name Publisher instance name (used for logging).
+ /// @param shared_memory_path POSIX shared memory name (e.g. /td_svt_ipc).
PublisherImpl(const std::string& name, const std::string& shared_memory_path) noexcept
: ReactiveMachine(name), Consumer(), shm_handler_{shared_memory_path}
{
@@ -43,7 +63,21 @@ class PublisherImpl : public ReactiveMachine, public Consumer
PublisherImpl& operator=(PublisherImpl&&) = delete;
~PublisherImpl() override = default;
+ /// @brief Initialises the shared memory IPC channel.
+ ///
+ /// Creates the backing shared memory segment for downstream readers via
+ /// @c SharedMemoryHandler::Init(). Must be called once before @c OnMessage().
+ ///
+ /// @return true if the shared memory segment was created successfully.
bool Init() override;
+
+ /// @brief Receives verified time data from the MessageBroker and publishes to shared memory.
+ ///
+ /// Converts @c DataType to @c IpcDataType via @c ConvertToIpcData(), then calls
+ /// @c SharedMemoryHandler::Send() which performs a single-writer atomic write
+ /// into the shared memory segment.
+ ///
+ /// @param data PtpTimeInfo from the @c verified_ptp_data topic.
void OnMessage(DataType data) override;
private:
diff --git a/score/time_daemon/src/ipc/core/receiver_impl.h b/score/time_daemon/src/ipc/core/receiver_impl.h
index 1cc905fc..94709a2d 100644
--- a/score/time_daemon/src/ipc/core/receiver_impl.h
+++ b/score/time_daemon/src/ipc/core/receiver_impl.h
@@ -22,13 +22,28 @@ namespace score
namespace td
{
+/// @brief IPC Machine receiver component for reading verified time data from
+/// the shared memory channel written by @c PublisherImpl.
///
-/// \brief Receiver impl class to receive data from ipc
+/// Opens an existing shared memory channel and reads the latest IPC-formatted
+/// time data. Used by the VehicleClock backend on the application
+/// side to retrieve time information from TimeDaemon.
///
+/// Thread-safe for multiple concurrent readers.
+/// @c SharedMemoryHandler::Receive() returns the latest snapshot atomically.
+/// The call is non-blocking and returns @c std::nullopt if no data is available.
+///
+/// @tparam IpcDataType Shared memory IPC data type (e.g. @c svt::TimeBaseSnapshot).
+///
+/// @see SvtReceiver Type alias for ReceiverImpl
+/// @see PublisherImpl TimeDaemon-side publisher component
template
class ReceiverImpl : public Receiver
{
public:
+ /// @brief Constructs the IPC receiver with a shared memory path.
+ ///
+ /// @param shared_memory_path POSIX shared memory name matching the publisher (e.g. /td_svt_ipc).
ReceiverImpl(const std::string& shared_memory_path) noexcept
: Receiver(), shm_handler_{shared_memory_path}
{
@@ -40,8 +55,19 @@ class ReceiverImpl : public Receiver
ReceiverImpl& operator=(ReceiverImpl&&) = delete;
~ReceiverImpl() override = default;
+ /// @brief Opens the existing shared memory IPC channel created by the publisher.
+ ///
+ /// Connects to the already-created segment by name; does not create a new segment.
+ /// Non-blocking; returns false immediately if segment not found.
+ ///
+ /// @return true if the shared memory segment was opened successfully.
bool Init() noexcept override;
+ /// @brief Reads the latest time data from shared memory.
+ ///
+ /// Non-blocking. Returns @c std::nullopt if no new or valid sample is available.
+ ///
+ /// @return Latest IPC data if available, @c std::nullopt otherwise.
std::optional Receive() noexcept override;
private:
diff --git a/score/time_daemon/src/msg_broker/msg_broker.h b/score/time_daemon/src/msg_broker/msg_broker.h
index 6aac807d..f74e4db4 100644
--- a/score/time_daemon/src/msg_broker/msg_broker.h
+++ b/score/time_daemon/src/msg_broker/msg_broker.h
@@ -28,17 +28,40 @@ namespace score
namespace td
{
+/// @brief Central publish-subscribe communication hub within the TimeDaemon.
///
-/// \brief Class to store each subscriber for dedicated topic. Idea is simple, any component can use subscribe with
-/// dedicated callback
-/// for explicit "topic". Then callback will be invoked when some component will call OnNewData() for dedicated
-/// topic.
+/// Manages topics and distributes messages to interested subscribers, enabling
+/// decoupled communication: components evolve independently without direct
+/// dependencies on each other.
///
+/// MessageBroker does not provide synchronization between publish and callback
+/// invocation. Callbacks run synchronously in caller's thread; no queuing.
+/// To separate control flows, use @c ControlFlowDivider.
+///
+/// @tparam T Message data type for this broker instance (e.g. PtpTimeInfo).
+///
+/// @see ControlFlowDivider For control flow separation between threads.
template
class MessageBroker : public std::enable_shared_from_this>
{
public:
+ /// @brief Registers a consumer component to receive messages on the specified topic.
+ ///
+ /// Creates a subscription wrapping the consumer's @c OnMessage() callback and
+ /// adds it to the topic registry. Uses a weak_ptr to avoid prolonging the
+ /// consumer's lifetime.
+ ///
+ /// @param topic Topic name to subscribe to.
+ /// @param subscriber_weak Weak pointer to the consumer component.
void AddSubscriber(const Topic& topic, std::weak_ptr> subscriber_weak);
+
+ /// @brief Registers a producer component to publish messages on the specified topic.
+ ///
+ /// Sets the producer's publish callback to invoke @c OnNewData() on this broker.
+ /// Uses a weak_ptr to avoid prolonging the producer's lifetime.
+ ///
+ /// @param topic Topic name to publish on.
+ /// @param producer_weak Weak pointer to the producer component.
void AddProducer(const Topic& topic, std::weak_ptr> producer_weak);
private:
diff --git a/score/time_daemon/src/ptp_machine/core/ptp_machine.h b/score/time_daemon/src/ptp_machine/core/ptp_machine.h
index 5a3dcd28..5b7855aa 100644
--- a/score/time_daemon/src/ptp_machine/core/ptp_machine.h
+++ b/score/time_daemon/src/ptp_machine/core/ptp_machine.h
@@ -27,25 +27,34 @@ namespace score
namespace td
{
-/**
- * @brief Manages time synchronization by interfacing with the PTP engine.
- *
- * The PTPMachine class abstracts the interaction with the Precision Time Protocol (PTP) engine,
- * periodically retrieving time information and publishing it to interested subscribers.
- * It handles initialization, deinitialization, and error recovery for the PTP stack,
- * ensuring reliable and up-to-date time data delivery within the system.
- */
+/// @brief Retrieves raw PTP time data from the PTP stack and publishes it to
+/// the MessageBroker.
+///
+/// Wraps platform-specific PTP stack communication (e.g. ptpd via devctl or
+/// gPTP shared memory), making stack implementations exchangeable. Runs in a
+/// dedicated thread via @c PeriodicMachine to maintain a consistent publishing
+/// rate even when PTP stack communication experiences delays.
+///
+/// Data flow per period:
+/// 1. @c PeriodicTask() called at the configured update interval.
+/// 2. @c ReadPTPSnapshot() retrieves raw data from the PTP stack via @c engine_impl_.
+/// 3. Data published to MessageBroker as the @c raw_ptp_data topic.
+/// 4. @c ControlFlowDivider receives it and separates control flow for the pipeline.
+///
+/// @tparam PTPEngine Platform-specific PTP stack interface (e.g. ShmPTPEngine).
+///
+/// @see ControlFlowDivider For control flow separation.
+/// @see PtpTimeInfo For the data structure definition.
+/// @see PeriodicMachine For the threading model.
template
class PTPMachine final : public PeriodicMachine, public Producer
{
public:
- /**
- * @brief Constructs a PTPMachine with the specified name, update interval, and PTP engine arguments.
- *
- * @param name The name of the PTPMachine instance.
- * @param updateInterval The interval at which time data is retrieved and published.
- * @param args Arguments forwarded to the PTPEngine constructor.
- */
+ /// @brief Constructs a PTPMachine with the specified name, update interval, and PTP engine arguments.
+ ///
+ /// @param name The name of the PTPMachine instance.
+ /// @param updateInterval The interval at which time data is retrieved and published.
+ /// @param args Arguments forwarded to the PTPEngine constructor.
template
explicit PTPMachine(const std::string& name, std::chrono::milliseconds updateInterval, PTPEngineArgs&&... args)
: PeriodicMachine(name, updateInterval),
@@ -65,51 +74,40 @@ class PTPMachine final : public PeriodicMachine, public Producer
PTPMachine(PTPMachine&&) = delete;
PTPMachine& operator=(PTPMachine&&) = delete;
- /**
- * @brief Initializes the PTP stack and prepares the machine for operation.
- *
- * Attempts to establish communication with the underlying PTP engine.
- * This method should be called before starting periodic time synchronization tasks.
- *
- * @return true if initialization was successful, false otherwise
- */
+ /// @brief Initialises the PTP stack and prepares the machine for operation.
+ ///
+ /// Attempts to establish communication with the underlying PTP engine.
+ /// Must be called before starting periodic time synchronisation tasks.
+ ///
+ /// @return true if initialisation was successful, false otherwise.
bool Init() override;
- /**
- * @brief Sets the callback function to be invoked when publishing data.
- *
- * @param callback Function to be called when data is published
- */
+ /// @brief Sets the callback function to be invoked when publishing data.
+ ///
+ /// @param callback Function to be called when data is published.
void SetPublishCallback(std::function callback) override;
protected:
- /**
- * @brief Periodically retrieves and publishes the latest PTP time data.
- *
- * Invoked at each update interval, this method obtains the current time information
- * from the PTP engine and publishes it to subscribers. Handles error recovery if the
- * PTP stack is not initialized or data retrieval fails.
- */
+ /// @brief Periodically retrieves and publishes the latest PTP time data.
+ ///
+ /// Invoked at each update interval by the PeriodicMachine worker thread.
+ /// Obtains the current time information from the PTP engine and publishes
+ /// it to subscribers. On read failure or uninitialised engine, calls
+ /// @c Deinit() and retries on the next interval.
void PeriodicTask() noexcept override;
private:
- /**
- * @brief Deinitializes the PTP stack and releases associated resources.
- *
- * Cleans up the connection to the underlying PTP engine and resets the internal state.
- *
- * @return true if deinitialization was successful, false otherwise
- */
+ /// @brief Deinitialises the PTP stack and releases associated resources.
+ ///
+ /// Cleans up the connection to the underlying PTP engine and resets the internal state.
void Deinit();
- /**
- * @brief Publishes time information data to registered subscribers.
- *
- * @param data The time information to publish
- */
+ /// @brief Publishes time information data to the registered subscribers.
+ ///
+ /// @param data The time information to publish.
void Publish(const PtpTimeInfo& data) override;
- /** @brief Callback function invoked when publishing data */
+ /// @brief Callback invoked when publishing data.
std::function publish_callback_;
std::unique_ptr engine_impl_;
diff --git a/score/time_daemon/src/ptp_machine/shm/details/shm_ptp_engine.h b/score/time_daemon/src/ptp_machine/shm/details/shm_ptp_engine.h
index 4fdf9c3b..12a97599 100644
--- a/score/time_daemon/src/ptp_machine/shm/details/shm_ptp_engine.h
+++ b/score/time_daemon/src/ptp_machine/shm/details/shm_ptp_engine.h
@@ -25,13 +25,17 @@ namespace td
namespace details
{
-/**
- * @brief PTP engine that reads time data from the shared-memory IPC channel
- * written by TimeSlave via GptpIpcPublisher.
- *
- * Converts the ts_client/src-internal GptpIpcData to the TimeDaemon PtpTimeInfo
- * data model.
- */
+/// @brief PTP engine implementation that reads @c GptpIpcData from the shared
+/// memory channel written by TimeSlave via @c GptpIpcPublisher.
+///
+/// Converts the @c GptpIpcData (ts_client-internal type) to the @c PtpTimeInfo
+/// structure expected by the TimeDaemon pipeline. Instantiated as
+/// @c GPTPShmMachine (type alias for @c PTPMachine),
+/// connecting this engine to the TimeDaemon MessageBroker.
+///
+/// @see CreateGPTPShmMachine Factory function.
+/// @see GptpIpcReceiver In ts_client, for the shared memory protocol.
+/// @see PTPMachine Template wrapper.
class ShmPTPEngine final
{
public:
@@ -43,10 +47,44 @@ class ShmPTPEngine final
ShmPTPEngine(ShmPTPEngine&&) = delete;
ShmPTPEngine& operator=(ShmPTPEngine&&) = delete;
+ /// @brief Opens the shared memory IPC channel written by TimeSlave.
+ ///
+ /// Calls @c GptpIpcReceiver::Init(ipc_name_) to map the shared memory
+ /// segment. Must be called once before @c ReadPTPSnapshot().
+ ///
+ /// @return @c true if the channel was opened successfully.
bool Initialize();
+ /// @brief Closes the shared memory IPC channel.
+ ///
+ /// Calls @c GptpIpcReceiver::Close() to unmap the shared memory region.
+ ///
+ /// @return @c true (always succeeds).
bool Deinitialize();
+ /// @brief Reads the latest gPTP snapshot from shared memory and converts it
+ /// to @c PtpTimeInfo.
+ ///
+ /// Calls @c GptpIpcReceiver::Receive() then performs a field-by-field
+ /// mapping from @c GptpIpcData to @c PtpTimeInfo:
+ ///
+ /// | @c GptpIpcData field | @c PtpTimeInfo field |
+ /// |---------------------------------|------------------------------------------------|
+ /// | @c ptp_assumed_time | @c ptp_assumed_time |
+ /// | @c local_time | @c local_time (wrapped in ReferenceClock::time_point) |
+ /// | @c rate_deviation | @c rate_deviation |
+ /// | @c status.is_synchronized | @c status.is_synchronized |
+ /// | @c status.is_timeout | @c status.is_timeout |
+ /// | @c status.is_time_jump_future | @c status.is_time_jump_future |
+ /// | @c status.is_time_jump_past | @c status.is_time_jump_past |
+ /// | @c status.is_correct | @c status.is_correct |
+ /// | @c sync_fup_data.* (9 fields) | @c sync_fup_data.* (direct copy) |
+ /// | @c pdelay_data.* (12 fields) | @c pdelay_data.* (direct copy) |
+ ///
+ /// All @c GptpIpcData fields mapped 1:1. Unmapped @c PtpTimeInfo fields zero-initialized.
+ ///
+ /// @param info Output parameter filled with the converted snapshot.
+ /// @return @c true if a valid snapshot was read; @c false otherwise.
bool ReadPTPSnapshot(PtpTimeInfo& info);
private:
diff --git a/score/time_daemon/src/verification_machine/core/verification_machine.h b/score/time_daemon/src/verification_machine/core/verification_machine.h
index 345e7899..14f59e81 100644
--- a/score/time_daemon/src/verification_machine/core/verification_machine.h
+++ b/score/time_daemon/src/verification_machine/core/verification_machine.h
@@ -29,28 +29,33 @@ namespace score
namespace td
{
-/**
- * @brief Machine component responsible for validating and qualifying time information.
- *
- * The VerificationMachine implements a pipeline pattern where each stage performs
- * specific validation and adds appropriate qualifiers to the provided data.
- */
+/// @brief Validates and qualifies time information received from the PTP Machine.
+///
+/// Implements a configurable pipeline pattern where each stage performs a
+/// specific validation and adds appropriate qualifiers to the provided data.
+/// The pipeline is assembled at construction time from factory functions.
+///
+/// Typical validation stages:
+/// 1. Sync state validation
+/// 2. Timeout detection
+/// 3. Time jump detection (forward / backward)
+///
+/// @tparam DataType The data type being validated (e.g. PtpTimeInfo).
template
class VerificationMachine final : public ReactiveMachine, public Consumer, public Producer
{
public:
- /**
- * @brief Constructor for VerificationMachine with validator factories.
- *
- * Each factory creates one validation stage. Stages are processed in the order
- * they are provided (first factory creates first stage in pipeline).
- *
- * @tparam Factories Types of factory functions
- * @param name The name of this verification machine instance
- * @param factories Factory functions to create each validator. Each factory
- * must return a unique_ptr to a VerificationStage.
- * Factories can be lambdas, std::bind expressions, or function pointers.
- */
+ /// @brief Constructs a VerificationMachine from a set of validator factories.
+ ///
+ /// Each factory creates one validation stage. Stages are processed in the order
+ /// they are provided (first factory creates first stage in pipeline).
+ ///
+ /// @tparam Factories Types of factory functions.
+ /// @param name The name of this verification machine instance.
+ /// @param factories Factory functions to create each validator. Each factory
+ /// must return @c unique_ptr>;
+ /// nullptr causes assertion. Factories can be lambdas, @c std::bind
+ /// expressions, or function pointers.
template
explicit VerificationMachine(const std::string& name, Factories&&... factories)
: ReactiveMachine(name), Consumer(), Producer(), pipeline_(), publish_callback_()
@@ -68,33 +73,23 @@ class VerificationMachine final : public ReactiveMachine, public Consumer callback) override;
- /**
- * @brief Process the received time information.
- *
- * This method is responsible for processing the time information data.
- *
- * @param data The time information data to be processed
- */
+ /// @brief Receives time information, runs it through the validation pipeline, and publishes the result.
+ ///
+ /// @param data The time information data to be processed.
void OnMessage(DataType data) override;
- /**
- * @brief Initialize machine
- *
- * As there is no explicit Init actions, it will be stubbed and return true.
- *
- * @param bool Init result
- */
+ /// @brief Initialize the machine. Stubbed — returns true immediately as no
+ /// explicit initialization actions are required.
+
+ /// @return true
bool Init() override;
private:
@@ -103,30 +98,23 @@ class VerificationMachine final : public ReactiveMachine, public Consumer;
using StageFactory = std::function;
- /**
- * @brief Publishes the time information data using the registered callback.
- *
- * This method invokes the previously set publish callback to distribute
- * the data to interested consumers.
- *
- * @param data The data to be published
- */
+ /// @brief Publishes the time information data using the registered callback.
+ ///
+ /// @param data The data to be published.
void Publish(const DataType& data) override;
- /**
- * @brief Sets up the validation pipeline by creating and connecting stages.
- */
+ /// @brief Sets up the validation pipeline by creating and connecting stages.
+ ///
+ /// Stages are connected in factory order: output of stage N becomes input of stage N+1.
void SetupPipeline(const std::vector& factories);
- /**
- * @brief Processes time information through the validation pipeline.
- *
- * @param data The time information to validate
- * @return The validated and qualified time information
- */
+ /// @brief Runs data through all validation pipeline stages sequentially.
+ ///
+ /// @param data The time information to validate.
+ /// @return The validated and qualified time information.
auto ProcessMessage(DataType data) -> DataType;
- /** @brief First stage in the validation pipeline */
+ /// @brief First stage in the validation pipeline.
std::unique_ptr pipeline_;
std::function publish_callback_;