我在
cnats
库周围有一个 RAII 包装器。我们不需要了解cnats
的细节。只有两个重要的部分。 cnats
是用于与 NATS 消息代理通信的 C 客户端。通常情况下,他们的所有结构都有自定义创建和删除功能。
我有一个用于创建
natsMsg
对象的 RAII 包装器。构造函数:
NatsMessage(const std::string& subject, const std::string& data) {
natsMsg* temp;
HANDLE_STATUS(natsMsg_Create(&temp, subject.c_str(), nullptr, data.c_str(), data.size()));
msg = std::shared_ptr<natsMsg>(temp, [](natsMsg* p) {natsMsg_Destroy(p);});
}
有两个发布功能:
js_PublishMsg
和js_PublishMsgAsync
。常规功能只是发布消息。我目前正在添加对异步版本的支持,它接管消息并在完成时调用natsMsg_Destroy
,导致竞争条件和双重免费错误。
来自阅读
std::shared_ptr
:
一个对象的所有权只能通过复制构造或复制赋值给另一个shared_ptr来与另一个shared_ptr共享。
std::unique_ptr
有相似的语言。
本质上我的问题是我想将 smart_pointer 与自定义删除器一起使用。当我调用异步发布函数时,我想以某种方式“删除”所有权,以便 c 库处理删除。
我可以切换到
unique_ptr
或其他智能指针(或其他实现此目的的方式)。
如果你不需要共享所有权,你可以使用具有
std::unique_ptr
功能的
release()
struct NatsMessage{
NatsMessage() {
natsMsg* temp;
GetMsg(&temp);
msg.reset(temp);
// when you need to transfer ownership to C library
// natsMsg* m = msg.release();
}
std::unique_ptr<natsMsg,decltype(&natsMsg_Destroy)> msg = {nullptr, &natsMsg_Destroy};
};
如果你想继续使用
std::shared_ptr
,你可以设置一些标志来禁用删除器。
你也可以使用原始指针并在析构函数中手动释放它,注意这也需要正确处理复制/移动案例。