FreeRTOS队列周围的C ++ wapper可以简化为:
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
州的文件:
The item is queued by copy, not by reference.
不幸的是,副本字面,因为它都以memcpy
结尾,这是有道理的,因为它是一个C API。虽然这适用于普通旧数据,但更复杂的项目(如以下事件消息)会产生严重问题。
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超出范围时,过早删除被保持对象。
我可以通过使用动态分配的T
- 实例来解决这个问题,并将队列更改为仅包含指向实例的指针,但我不想这样做,因为这应该在嵌入式系统上运行而我非常希望在运行时保持内存静态。
我目前的计划是更改队列以包含指向包装器类中本地保存的内存区域的指针,我可以在其中实现完整的C ++对象复制,但是我还需要保护该内存区域多线程访问,它本质上打败了FreeRTOS队列的已经线程安全的实现(这肯定比我自己编写的任何实现都更有效)我不妨完全跳过它们。
最后,问题是:
在我实现自己的队列之前,我是否有任何技巧可以使用C ++对象实例来实现FreeRTOS队列功能,特别是std::shared_ptr
?
答案 0 :(得分:0)
问题是将指针放入队列后原始文件会发生什么。 复制看似微不足道,但并非最佳。
为了解决这个问题,我使用邮箱而不是队列:
T* data = (T*) osMailAlloc(m_mail, osWaitForever);
...
osMailPut (m_mail, data);
从哪里开始显式分配指针。只需将指针添加到邮箱即可。
并检索:
osEvent ev = osMailGet(m_mail, osWaitForever);
...
osStatus freeStatus = osMailFree(m_mail, p);
所有都可以整齐地扭曲到 C++ 模板方法中。