C++ moodycamel 并发队列 - 排队指针

C++ moodycamel concurrent queue - enqueue pointers

我正在尝试使用 ConcurrentQueue 将项目记录到单独线程上的文件中:

https://github.com/KjellKod/Moody-Camel-s-concurrentqueue

这个有效:

// declared on the top of the file
moodycamel::ConcurrentQueue<MyType> q; // logger queue
. . .
int MyCallbacks::Event(MyType* p)
{
   MyType item = (MyType)*p;
   q.enqueue(item);
. . .
// pthread
void* Logger(void* arg) {

    MyType.item;

    while (true)
        if (!q.try_dequeue(item))

这没有(对象在出列后似乎已损坏:

// declared on the top of the file
moodycamel::ConcurrentQueue<MyType*> q; // logger queue
. . .
int MyCallbacks::Event(MyType* p)
{
   MyType item = (MyType)*p;
   q.enqueue(&item);
. . .
// pthread
void* Logger(void* arg) {

    MyType* item;

    while (true)
        if (!q.try_dequeue(item))

也在 Event 中尝试过这个 - 仍然不起作用(&newdata 总是打印相同的地址):

auto newdata = std::move(data);
printf("  - pointers - new: %p old: %p\n", &newdata, &data);
q.enqueue(&newdata);

是我做错了还是队列不支持指针?

以下代码:

int MyCallbacks::Event(MyType* p)
{
   MyType item = (MyType)*p;
   q.enqueue(&item);

有一个主要缺陷:您将指向 local 变量的指针放入队列 item.

Event函数returns一到,item的life-time就结束了,就被析构了。您保存的指向它的指针将无效。取消引用该无效指针将导致未定义的行为

根本不需要在此处创建本地副本,您应该可以直接使用 p,包括将其添加到队列中:

q.enqueue(p);

话虽如此,您不需要演员表

MyType item = (MyType)*p;

*p的类型已经MyType。一般而言,当您觉得有必要进行这样的 C-style 转换时,您应该将其视为您做错事的标志。


如果您需要一个副本,为什么不创建一个新对象到 copy-initialize?

喜欢:

MyItem* item = new MyItem(*p);
q.enqueue(item);

你当然要记得 delete 一旦你完成了这个对象。

比使用原始 non-owning 指针更好的解决方案是使用像 std::unique_ptr:

这样的智能指针
moodycamel::ConcurrentQueue<std::unique_ptr<MyType>> q; // logger queue

// ...

q.enqueue(std::make_unique<MyItem>(*p));