我正在使用一些API来获取通知。就像是:
NOTIF_HANDLE register_for_notif(CALLBACK func, void* context_for_callback);
void unregister_for_notif(NOTIF_HANDLE notif_to_delete);
我想将其包装在一些不错的RAII类中,该类将在收到通知后设置事件。我的问题是如何同步它。我写了这样的东西:
class NotifClass
{
public:
NotifClass(std::shared_ptr<MyEvent> event):
_event(event),
_notif_handle(register_for_notif(my_notif_callback, (void*)this))
// initialize some other stuff
{
// Initialize some more stuff
}
~NotifClass()
{
unregister_for_notif(_notif_handle);
}
void my_notif_callback(void* context)
{
((NotifClass*)context)->_event->set_event();
}
private:
std::shared_ptr<MyEvent> _event;
NOTIF_HANDLE _notif_handle;
};
但是我担心构造/销毁期间会调用回调(也许在此特定示例中,shared_ptr可以很好地使用它,但也许与其他构造的类不一样)。
我会再说一遍-我不希望为这个非常特殊的类提供一个非常具体的解决方案,而是在传递回调时为RAII提供一个更通用的解决方案。
您对同步的关注有点放错了地方。
总结一下您的问题,您可以使用一些库来注册一个回调函数,并(通过void *指针或类似的东西)注册一些资源,这些资源可通过一个register()
函数作用于该函数。该库也提供了一个unregister()
功能。
在您的代码中,您既不能也不应尝试避免库在通过unregister()
函数注销之后或之后可以调用您的回调函数的可能性:库的责任是确保在回调过程中不能触发该回调正在取消注册。图书馆应该担心同步化,互斥和其他小问题,而不是您。
您的代码的两个职责是:
C的构造与破坏的相反顺序正是C ++对其成员变量所做的,以及为什么编译器在以“错误”顺序初始化它们时会警告您。
就您的示例而言,您需要确保1)register_for_notif()
在初始化共享指针之后被调用,并且2)unregister_for_notif()
在std :: shared_ptr(或其他任何东西)被销毁之前被调用。
后者的关键是了解析构函数中破坏的顺序。作为回顾,请查看以下cppreference.com页面的“销毁序列”部分。
因此,示例代码是“安全的”(或尽可能安全),因为unregister_for_notif()
在销毁成员变量之前在析构函数主体中对其进行了调用std::shared_ptr<MyEvent> _event
。
进行此操作的另一种方法(从某种意义上来说更明确地遵循RAII的方式)是将通知句柄与回调函数所运行的资源分开,方法是将其拆分为自己的类。例如:
class NotifHandle {
public:
NotifHandle(void (*callback_fn)(void *), void * context)
: _handle(register_for_notif(callback_fn, context)) {}
~NotifHandle() { unregister_for_notif(_handle); }
private:
NOTIF_HANDLE _handle;
};
class NotifClass {
public:
NotifClass(std::shared_ptr<MyEvent> event)
: _event(event),
_handle(my_notif_callback, (void*)this) {}
~NotifClass() {}
static void my_notif_callback(void* context) {
((NotifClass*)context)->_event->set_event();
}
private:
std::shared_ptr<MyEvent> _event;
NotifHandle _handle;
};
重要的是成员变量声明顺序:NotifHandle _handle
在资源之后声明std::shared_ptr<MyEvent> _event
,因此可以确保在销毁资源之前取消通知的注册。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句