FreeRTOS 中的共享指针和队列 [英] Shared pointers and queues in FreeRTOS
问题描述
围绕 FreeRTOS 队列的 C++ wapper 可以简化为如下所示:
A C++ wapper around a FreeRTOS queue can be simplified into something like this:
template<typename T>
class Queue<T>
{
public:
bool push(const T& item)
{
return xQueueSendToBack(handle, &item, 0) == pdTRUE;
}
bool pop(T& target)
{
return xQueueReceive(handle, &target, 0) == pdTRUE;
}
private:
QueueHandle_t handle;
}
xQueueSendToBack
的文档说明:
<代码>该项目按副本排队,而不是按引用排队.
不幸的是,它字面意思是复制的,因为它都以memcpy
结尾,这是有道理的,因为它是一个C API.虽然这适用于普通的旧数据,但更复杂的项目(例如以下事件消息)会带来严重问题.
Unfortunately, it is literally by copy, because it all ends in a memcpy
, which makes sense since it is a C API. While this works well for plain old data, more complex items such as the following event message give serious problems.
class ConnectionStatusEvent
{
public:
ConnectionStatusEvent() = default;
ConnectionStatusEvent(std::shared_ptr<ISocket> sock)
: sock(sock)
{
}
const std::shared_ptr<ISocket>& get_socket() const
{
return sock;
}
private:
const std::shared_ptr<ISocket> sock;
bool connected;
};
问题显然是 std::shared_ptr
根本不适用于 memcpy
,因为它的复制构造函数/赋值运算符在复制到队列,导致当事件消息和 shared_ptr 超出范围时过早删除持有的对象.
The problem is obviously the std::shared_ptr
which doesn't work at all with a memcpy
since its copy constructor/assignment operator isn't called when copied onto the queue, resulting in premature deletion of the held object when the event message, and thus the shared_ptr, goes out of scope.
我可以通过使用动态分配的 T
实例来解决这个问题,并将队列更改为仅包含指向该实例的指针,但我不想这样做,因为这将在嵌入式系统上运行并且我非常希望在运行时保持内存静态.
I could solve this by using dynamically allocated T
-instances and change the queues to only contain pointers to the instance, but I'd rather not do that since this shall run on an embedded system and I very much want to keep the memory static at run-time.
我目前的计划是更改队列以包含指向包装类中本地保存的内存区域的指针,我可以在其中实现完整的 C++ 对象复制,但因为我还需要保护该内存区域免受多个线程的影响访问,它本质上破坏了 FreeRTOS 队列的已经线程安全的实现(这肯定比我自己编写的任何实现更有效),我不妨完全跳过它们.
My current plan is to change the queue to contain pointers to a locally held memory area in the wrapper class in which I can implement full C++ object-copy, but as I'd also need to protect that memory area against multiple thread access, it essentially defeats the already thread-safe implementation of the FreeRTOS queues (which surely are more efficient than any implementation I can write myself) I might as well skip them entirely.
最后,问题:
在我实现自己的队列之前,有没有什么技巧可以让我使用 C++ 对象实例(尤其是 std::shared_ptr
)使 FreeRTOS 队列功能?
Before I implement my own queue, are there any tricks I can use to make the FreeRTOS queues function with C++ object instances, in particular std::shared_ptr
?
推荐答案
问题是将指针放入队列后原始文件会发生什么.复制看似微不足道,但并非最佳.
The issue is what happens to the original once you put the pointer into the queue. Copying seems trivial but not optimal.
为了解决这个问题,我使用邮箱而不是队列:
To get around this issue i use a mailbox instead of a queue:
T* data = (T*) osMailAlloc(m_mail, osWaitForever);
...
osMailPut (m_mail, data);
从哪里开始显式分配指针.只需将指针添加到邮箱即可.
Where you allocate the pointer explicitly to begin with. And just add the pointer to the mailbox.
并检索:
osEvent ev = osMailGet(m_mail, osWaitForever);
...
osStatus freeStatus = osMailFree(m_mail, p);
所有都可以整齐地扭曲到 C++ 模板方法中.
All can be neatly warpend into c++ template methods.
这篇关于FreeRTOS 中的共享指针和队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!