FreeRTOS中的共享指针和队列

Per*_*Per 5 shared-ptr freertos

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;
}
Run Code Online (Sandbox Code Playgroud)

xQueueSendToBack各州的文件:

The item is queued by copy, not by reference.

不幸的是,它实际上是通过副本,因为它都以a结尾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;
};
Run Code Online (Sandbox Code Playgroud)

问题显然std::shared_ptrmemcpy由于复制构造函数/赋值运算符在复制到队列时未被调用,因此根本不起作用,导致在事件消息以及shared_ptr进行时过早删除保留的对象超出范围.

我可以通过使用动态分配T的实例来解决这个问题,并将队列更改为仅包含指向实例的指针,但我宁愿不这样做,因为这应该在嵌入式系统上运行,我非常希望在运行时保持内存静态-时间.

我当前的计划是更改队列以包含指向包装器类中本地保存的内存区域的指针,我可以在其中实现完整的C++对象复制,但是我还需要保护该内存区域以防止多线程访问,本质上打败了FreeRTOS队列的已经线程安全的实现(这肯定比我自己编写的任何实现都更有效)我不妨完全跳过它们.

最后,问题是:

之前,我实现我自己的队列,在那里我可以用它来使FreeRTOS的队列,C函数++对象的情况下,特别是什么招数std::shared_ptr

小智 0

问题是一旦将指针放入队列中,原始数据会发生什么。复制看似微不足道,但并不是最佳选择。

为了解决这个问题,我使用邮箱而不是队列:

T* data = (T*) osMailAlloc(m_mail, osWaitForever);
...
osMailPut (m_mail, data);
Run Code Online (Sandbox Code Playgroud)

从哪里开始显式分配指针。只需将指针添加到邮箱即可。

并检索:

osEvent ev = osMailGet(m_mail, osWaitForever);
...
osStatus freeStatus = osMailFree(m_mail, p);
Run Code Online (Sandbox Code Playgroud)

所有这些都可以巧妙地变形为 C++ 模板方法。