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
.