Platform module

DDS discovery datacentric memory execution serialization platform protocol transport portable system toolchain

In Safe DDS, all operations related to the platform are executed by the Platform module, which has been designed to be responsible for the following tasks:

  • Management of memory allocation calls, ensuring that all the possible memory allocations are performed via platform interfaces.

  • Handling of fatal errors, allowing for appropriate responses to critical issues that may arise during the library’s operation.

  • Control of timing mechanisms, providing platform specific timekeeping for various processes within the library.

By delegating these essential functions to the platform module, it is possible to maintain a streamlined and organized structure within Safe DDS, ultimately contributing to its reliability, performance and portability.

Default platform

If Safe DDS has been built with any built-in platform support using the SAFEDDS_TRANSPORT flag via CMake options, the default platform can be retrieved using the system-wide get_platform method. Analogously, a system-wide default platform can be set using the set_platform method. This API will be used internally by multiple Safe DDS modules to perform platform related operations.

// Retrieve the default platform (depends on the platform implementation built).
platform::IPlatform& platform = get_platform();

// Setting a default platform at runtime.
CustomPlatform custom_platform;
set_platform(custom_platform);

IPlatform interface

IPlatform is the interface that all platform module implementation must implement.

API Reference

For more information about transport::IPlatform interface, check API Reference:

Memory management

Safe DDS memory operations are performed using the allocate method of the platform module. This method is responsible for allocating memory blocks of the specified size, and returning a pointer to the beginning of the allocated memory.

It is important to note that the memory allocated will not be deallocated, meaning that Safe DDS will provide mechanisms for controlling the memory allocations performed by the different modules.

At DDS level, these memory allocations can be controlled by means of the PreallocMemoryConfig and related QoS policies. Those policies allows for specifying the maximum amount of elements that a certain entity will be able to allocate, and also allow for the application to specify how many of those elements shall be preallocated at creation time.

Safe DDS Usage

Note that the Safe DDS static API, detailed at StaticDomainParticipant, StaticTopic, StaticPublisher, StaticSubscriber, StaticDataWriter and StaticDataReader, does not leverage the memory allocation mechanism provided by the platform module.

If the Safe DDS Static DDS API is used, it is safe to override the allocate method of the platform module to return nullptr.

Safe DDS Usage

For a complete reference of the different memory objects used in Safe DDS, please refer to Memory module.

The allocate function of platform::IPlatform returns a void * pointer to the beginning of the allocated memory and takes the following arguments:

  • size as size_t

    The size of the memory block to be allocated.

Error handling

Safe DDS will use the fatal_error method of the platform module to handle fatal errors during the library’s operation. This method shall not return as it is called when the library is in an unrecoverable state.

Time keeping

Safe DDS will use the get_current_timepoint method of the platform module to retrieve the current time. This method shall return a monotonic timepoint as an execution::TimePoint object and takes no arguments.

Example implementation

A naive IPlatform interface implementation could be:

class CustomPlatform : public platform::IPlatform
{
    execution::TimePoint get_current_timepoint() noexcept override
    {
        // Platform specific function to retrieve time (in this case in ms) [NOT PROVIDED]
        size_t millis = system_get_millis();

        execution::TimePoint timepoint = {};
        timepoint.seconds = millis / 1000;
        timepoint.nanoseconds = (millis % 1000) * 1000000;

        return timepoint;
    }

    [[noreturn]] void fatal_error(
            const char* msg) noexcept override
    {
        printf("Fatal error: %s\n", msg);
        while (1)
        {
        }
    }

    void* allocate(
            size_t size) noexcept override
    {
        return malloc(size);
    }

};