exos_datamodel_set_process_mode()

<< 点击显示目录 >>

主页  exOS使用助手 > exOS Automation Help > Development > Programming > exOS Communication API reference (exos_api.h) >

exos_datamodel_set_process_mode()

为 Linux 设置 exos_datamodel_process() 函数的行为(阻塞/非阻塞)

声明

类型化枚举
{
 exos_datamodel_process_blocking、
 exos_datamodel_process_non_blocking
}exos_datamodel_process_mode;
EXOS_ERROR_CODE exos_datamodel_set_process_mode(exos_datamodel_handle_t *datamodel, EXOS_DATAMODEL_PROCESS_MODE mode);

在 Linux 中,exos_datamodel_process() 的默认行为是阻塞并等待同步事件。该事件由 AR 中的 DMR 任务类触发,允许 Linux 进程与 AR 任务类系统同时运行。这种同步还允许 Linux 程序在每次调用 exos_datamodel_process() 之后发布一条消息,而不会出现缓冲区溢出的情况,并且可以循环方式来回发送值,即每次任务类扫描都会更新一次。这对于与运行时系统紧密交互的 Linux 进程尤其有用。

不过,在某些情况下,调用 exos_datamodel_process()(无需同步(阻塞)行为),只需从存储在缓冲区的 AR 中读取更新的数据集即可。值得一提的是,即使 exos_datamodel_process() 以非阻塞方式运行,Linux 仍会按照发布的顺序接收来自 AR 的所有已发布值。

函数 exos_datamodel_set_process_mode() 可在应用程序中随时调用,并立即更改 exos_datamodel_process() 的行为。

Parameters

数据模型

数据模型句柄,以指针形式给出

模式

EXOS_DATAMODEL_PROCESS_BLOCKING 表示 exos_datamodel_process() 在 Linux 中的预期行为。EXOS_DATAMODEL_PROCESS_BLOCKING 表示 exos_datamodel_process() 与 DMR 循环同步,而 EXOS_DATAMODEL_PROCESS_NON_BLOCKING 表示 exos_datamodel_process() 在读出可能传入的数据集变化后立即结束。有关同步的更多信息,请参阅 流程同步 章节。

在 AR 中,exos_datamodel_process() 始终是非阻塞的,将模式设置为 EXOS_DATAMODEL_PROCESS_BLOCKING 只会导致错误。

 

示例

在当前版本(2.1.0)的 Linux Dataset Message Router中,无法严格保证在所有数据发布到应用程序后才会发生 NETTIME 同步事件(在大约 1/100000 的情况下,NETTIME 同步事件会在数据发布后发生)。如果应用程序知道数据即将到来(在循环传输的情况下),可以使用非阻塞进程模式等待数据几毫秒。

#define WAIT_MAX 50 //wait at max 5ms for new data
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
    switch (event_type)
    {
    case EXOS_DATASET_EVENT_UPDATED:
        // as soon as data has been received (which is likely to have happened the first time process() is called in blocking mode)
        // set the tag for having received data
        dataset->datamodel->user_tag = 1;
    ..
    }
}
void main()
{
    ..
    //this is instead of doing a simple EXOS_ASSERT_OK(exos_datamodel_process(&myapplication));
    myapplication.user_tag = 0; //reset the tag for having received data
    uint8_t loops = 0;
    exos_datamodel_set_process_mode(&myapplication, EXOS_DATAMODEL_PROCESS_BLOCKING); //start with calling process() in a blocking manner
    do
    {
        EXOS_ASSERT_OK(exos_datamodel_process(&myapplication));
        loops++;
        if (myapplication.user_tag == 0) //if data was not received, set the non-blocking process mode and sleep
        {
            exos_datamodel_set_process_mode(&myapplication, EXOS_DATAMODEL_PROCESS_NON_BLOCKING);
            usleep(100);
        }
        //data.Sending indicates that the application should receive cyclic data (set from the AR application)
        //wait for cyclic data for 5ms
    } while (loops <= WAIT_MAX && (data.Sending) && myapplication.user_tag == 0);
    ..
}


 

Set the behavior of the exos_datamodel_process() function (blocking / non-blocking) for Linux

Declaration

typedef enum
{
    EXOS_DATAMODEL_PROCESS_BLOCKING,
    EXOS_DATAMODEL_PROCESS_NON_BLOCKING
} EXOS_DATAMODEL_PROCESS_MODE;
EXOS_ERROR_CODE exos_datamodel_set_process_mode(exos_datamodel_handle_t *datamodel, EXOS_DATAMODEL_PROCESS_MODE mode);

In Linux, the default behavior of exos_datamodel_process() is to block and wait for a synchronization event. This event is triggered by the DMR Task class in Automation Runtime, and allows Linux processes to run alongside the Automation Runtime task class system. This synchronization also allows Linux programs to publish a message after every call to exos_datamodel_process() without having any buffer overflows, and values can be sent back and forth in a cyclic manner, meaning being updated with every task class scan. This can be especially useful for Linux processes that are tightly interacting with the runtime system.

In some cases however, it can be useful to call exos_datamodel_process() without the synchronized (blocking) behaviour, in order to just read out updated datasets from AR which are stored in the buffers. It is important to mention that all published values from Automation Runtime are still received in Linux in the order these were published, even though the exos_datamodel_process() runs in a non-blocking manner.

The function exos_datamodel_set_process_mode() can be called at any time in the application, and changes the behaviour of exos_datamodel_process() immediately.

Parameters

datamodel:

datamodel handle, given as a pointer

mode:

Desired behavior for exos_datamodel_process() in Linux. EXOS_DATAMODEL_PROCESS_BLOCKING Means that the exos_datamodel_process() synchronizes with the DMR Cycle, and EXOS_DATAMODEL_PROCESS_NON_BLOCKING means that the exos_datamodel_process() finishes immediately after reading out possible incoming dataset changes. For more information regading synchronization, please refer to the Process Synchronization chapter.

In Automation Runtime, the exos_datamodel_process() is always non-blocking, and setting the mode to EXOS_DATAMODEL_PROCESS_BLOCKING just reults in an error.

Example

In the current version (2.1.0) of the Linux Dataset Message Router, there is no strict guarantee that data the NETTIME synchronization event comes after all data has been published to the application (in about 1/100000 of the cases, the NETTIME synchronization event comes after the data). The non-blocking process mode can be used to wait for the data a few milliseconds if the application knows that data is to be expected (in cases of cyclic transmission).

#define WAIT_MAX 50 //wait at max 5ms for new data
static void datasetEvent(exos_dataset_handle_t *dataset, EXOS_DATASET_EVENT_TYPE event_type, void *info)
{
    switch (event_type)
    {
    case EXOS_DATASET_EVENT_UPDATED:
        // as soon as data has been received (which is likely to have happened the first time process() is called in blocking mode)
        // set the tag for having received data
        dataset->datamodel->user_tag = 1;
    ..
    }
}
void main()
{
    ..
    //this is instead of doing a simple EXOS_ASSERT_OK(exos_datamodel_process(&myapplication));
    myapplication.user_tag = 0; //reset the tag for having received data
    uint8_t loops = 0;
    exos_datamodel_set_process_mode(&myapplication, EXOS_DATAMODEL_PROCESS_BLOCKING); //start with calling process() in a blocking manner
    do
    {
        EXOS_ASSERT_OK(exos_datamodel_process(&myapplication));
        loops++;
        if (myapplication.user_tag == 0) //if data was not received, set the non-blocking process mode and sleep
        {
            exos_datamodel_set_process_mode(&myapplication, EXOS_DATAMODEL_PROCESS_NON_BLOCKING);
            usleep(100);
        }
        //data.Sending indicates that the application should receive cyclic data (set from the AR application)
        //wait for cyclic data for 5ms
    } while (loops <= WAIT_MAX && (data.Sending) && myapplication.user_tag == 0);
    ..
}