通过一个带有void*的C接口传递shared_ptr

Edm*_*und 6 c++ sdl shared-ptr

我有一个使用SDL的C++项目,特别是SDL事件.我想将事件系统用于传入的网络消息,就像它用于UI事件一样.我可以定义一个新的事件类型并附加一些任意数据(参见这个例子).如果我使用普通指针,这就是我要做的事情:

Uint32 message_event_type = SDL_RegisterEvents(1);

/* In the main event loop */
while (SDL_Poll(&evt)) {
    if (evt.type == message_event_type) {
         Message *msg = evt.user.data1;
         handle_message(msg);
    }
}

/* Networking code, possibly in another thread */
Message *msg = read_message_from_network();
SDL_Event evt;
evt.type = message_event_type;
evt.user.data1 = msg;
SDL_PostEvent(evt);
Run Code Online (Sandbox Code Playgroud)

相反,我一直在使用shared_ptr<Message>.消息一旦构造就是只读对象,并且在处理时可能在很多地方使用,所以我想为它们使用shared_ptr.

我想将shared_ptr用于网络端的消息,也可以在事件处理端使用.如果我这样做:

// in networking code:
shared_ptr<Message> msg = ...
evt.user.data1 = msg.get();

// later, in event handling:
shared_ptr<Message> msg(evt.user.data1);
Run Code Online (Sandbox Code Playgroud)

然后有两个独立的shared_ptrs,任何一个都可以删除Message对象,而其中一个仍在使用它.我需要以某种方式通过SDL_UserEvent结构传递shared_ptr,该结构只有几个void *和int字段.

额外.注意SDL_PostEvent立即返回; 事件本身被放入队列中.在消息的shared_ptr超出网络代码范围之后,处理程序可能会从队列中弹出事件.所以我无法传递本地shared_ptr的地址来复制.复制发生时,它可能不再有效.

有没有人遇到类似的问题,并知道一个很好的解决方案?

Que*_*onC 6

使用new分配指向共享ptr的指针.这会调用构造函数(递增引用计数),但不会调用相应的析构函数,因此shared_ptr永远不会破坏它的共享内存.

然后在相应的处理程序中,只需在复制shared_ptr之后销毁该对象,使其引用计数恢复正常.

这与您通过消息队列传递任何其他非基本类型的方式相同.

typedef shared_ptr<Message> MessagePtr;

Uint32 message_event_type = SDL_RegisterEvents(1);

/* In the main event loop */
while (SDL_Poll(&evt)) {
    if (evt.type == message_event_type) {
         // Might need to cast data1 to (shared_ptr<Message> *)
         unique_ptr<MessagePtr> data (evt.user.data1);
         MessagePtr msg = *data;
         handle_message(msg);
    }
}

/* Networking code, possibly in another thread */
MessagePtr msg = read_message_from_network();
SDL_Event evt;
evt.type = message_event_type;
evt.user.data1 = new MessagePtr (msg); 
SDL_PostEvent(evt);
Run Code Online (Sandbox Code Playgroud)

消息是构造后的只读对象

我只是想指出,这对于多线程安全来说是好的甚至是必要的.你可能想用shared_ptr<const Message>


Ste*_*oft 5

似乎是理想的使用场所 std::enable_shared_from_this

struct Message: std::enable_shared_from_this<Message>
{
    …
};

evt.user.data1 = msg.get();

// this msg uses the same refcount as msg above
shared_ptr<Message> msg = evt.user.data1.shared_from_this();
Run Code Online (Sandbox Code Playgroud)

  • @qexyn`std :: shared_ptr` *是* C ++ 11及更高版本 (2认同)