首页 > 解决方案 > Implementing/replacement of volatile std::string

问题描述

As already noted here using volatile std::string isn't a good idea.

I'm developing an application on FreeRTOS and I need to have a string which is moved between tasks. There is one task which receives commands through UART and can be asked by other tasks to get the response on a specified command. I want to use std::move on a string to make the application optimal.

Is there a neat and fast replacement of volatile std::string or do I have to implement a class with volatile field on my own? Maybe this approach is bad and I should use another structure to handle moving around responses on the commands?

EDIT: Here's some code.

I get the single bytes of commands through interrupt. The commands are human readable commands terminated with \r.

void rx_interrupt(char c)
{
    if(c == '\r')
    {
        c == '\0')
        BaseType_t higher_prior_task_woken = pdFALSE;
        vTaskNotifyGiveFromISR(rx_task_handle, &higher_prior_task_woken);
        portYIELD_FROM_ISR(higher_prior_task_woken);
    }
    rx_buf.push_byte(c);
}

rx_buf is a circular buffer which allows to pop whole commands as std::string.

Then the rx_task:

for (;;)
{
    auto notif_num = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    while (notif_num--)
    {
        auto comm = rx_buf.pop_command();
        if (comm.length() == 0)
            continue;

        if (is_unsolicited_command(comm))
            handle_unsolicited_command(std::move(comm));
        if (is_awaited_command(comm))
            handle_awaited_command(std::move(comm));
    }
}

The rx_task is needed because I must firstly check whether an asynchronous event occurred which is indicated by an unsolicited command.

The received (awaited) commands may be long so I want to move them.

void handle_awaited_command(std::string &&cmd)
{
    os_lockguard guard(var_mux);
    if (!awaiting)
        return;

    awaited_command = std::move(cmd); // Problematic line
    xSemaphoreGive(cmd_received_sem);
    awaited_cmd_handled = true;
}

Finally any of the other task may await a command:

std::string get_command()
{
    os_lockguard guard_glob(mux);

    {
        os_lockguard guard(var_mux);
        awaiting = true;
    }

    xSemaphoreTake(cmd_received_sem, timeout);

    {
        os_lockguard guard(var_mux);
        if(awaited_cmd_handled)
            return std::move(awaited_command); // Problematic line
        else
            return std::string("");
    }
}

The thing is that the definitions looks like that:

volatile bool awaiting;
volatile bool awaited_cmd_handled;
volatile std::string awaited_command;

So I have here a volatile std::string.

标签: c++stringmove-semanticsvolatilefreertos

解决方案


推荐阅读