c – 我应该以哪种顺序发送callback()并通知服务员?

我有一个类,通过它我可以异步提供一些服务(同样的调用也可以同步进行).当请求时,此类的对象(比如运算符)在另一个线程中启动操作.其他对象可以注册到操作符对象的通知,以便在操作结束时对此对象调用OperationEnded()方法.其他对象也可以通过调用操作符对象上的Wait()来等待此操作的完成.

操作结束时的代码大致如下:

_opEndedMutex.lock();
_thereIsOngoingOp = false;
_opEndedCondition.notify_all();
_opEndedMutex.unlock();

//no more call after notification
m_spnotificationmanager->OperationEnded();

而wait()函数如下:

boost::unique_lock<boost::mutex> lock(_opEndedMutex);
while(_thereIsOngoingOp)
{
    _opEndedCondition.wait(_opEndedMutex);
}

问题在于资源管理.这是一个C类,因此当检测到操作结束时,此类的用户可能会删除操作符对象(如果有任何活动操作,析构函数将等待完成).可以通过等待或接受通知来检测操作的结束.因此,如果我首先调用_opEndedCondition.notify_all()并且用户删除操作符对象,则在尝试调用OperationEnded()时可能会崩溃,因为m_spnotificationmanager已被删除.如果选择首先调用OperationEnded()并且用户在此调用期间删除操作符对象,则在尝试访问_opEndedMutex,_thereIsOngoingOp和_opEndedCondition时可能会崩溃.

我想到的第一件事就是使用新的互斥锁来保护这两个调用.这看起来并不漂亮,因为我无法预见如果引入新的互斥锁会发生什么,并且如果在OperationEnded()通知用户同步启动新操作.我也不确定如何在wait()方法中使用新的互斥锁.

注1:此API用于我们自己公司和其他公司的应用程序.所以我无法摆脱任何一种同步机制.

注意2:我修改了原始代码,变量和方法名称,因此可能存在拼写错误,但这个想法应该是明确的.

EDIT1:

运算符对象保留在通过工厂生成的共享库中,然后通过接口暴露给外部世界.
所以操作符对象的典型生命周期如下:

IOperator * op = factory:getNewOperator();
//perform operations with op
op->Release() //this one goes and deletes the op object

另请注意,运算符对象是可重用的.客户端代码可以使新的操作符对象多次使用它并在最后删除它.

解决方法

你有几个解决方案:

>您可以从std::enable_shared_from_this专门化您的操作对象.这意味着在客户端代码中,您不再删除该对象,而是将std :: shared_ptr设置为nullptr,并且在实际删除对象时不关心.
>您可以在计时器延迟时实现有限的垃圾收集:当您在客户端代码中收到OperationEnded()通知时,您将获取指针并将其放在队列中,以及添加对象时的时间戳.然后队列将有一个活动对象在计时器上唤醒,占用当前时间,如果时间戳(比如说)比当前时间至少早五秒,则删除它.
>您可以使用object pool分配和取消分配操作类.当不再使用某个对象时,它实际上不会被删除,而是作为池中的免费(回收)对象放置.在完成处理后,当池被销毁时,实际上将删除该对象.>您可以为对象创建生命周期管理器,这将删除您的操作对象,然后发送通知.>你可以让’OperationEnded’函数调用删除这个;在末尾;然后,您将实现客户端代码,以便在接收通知时将指针设置为NULL;这样的解决方案虽然很脆弱,但实际上,这可能会将问题转移到另一段代码中.>最后,您可以实现所有这些的自定义组合.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...