多线程插件架构中的共享,单侧可变状态

时间:2015-02-20 14:24:37

标签: c++ multithreading c++11 synchronization c++14

我有一个应用程序,它有一个非常简单的插件系统,它围绕一个负责繁重工作的核心构建,但是除了基础之外还有任何处理过程。现在我想使该系统具有多线程,或者至少允许各个插件运行自己的线程,以便它们可以单独阻塞而不冻结核心。

当然,这意味着使核心线程安全,以便插件可以自由地操作所述核心的线程安全成员函数。对于许多情况来说,这并不难,但是当其中一个成员函数的结果是对由核心维护的某些内部环境的(const)引用时,就会出现问题。插件不能修改它,但是在另一个线程中运行的核心可以在任何时间点更新它,而插件仍然保留在引用上并且可能仍处于中间处理状态。

现在我可以在核心中暴露一个互斥锁并让插件锁定它,只要它们需要数据保持不变,但由于该互斥锁必须阻止核心事件处理,因此将其保持太久会导致各种不愉快。我真的很想避免这种情况。

另一个解决方案可能是具有返回引用的函数,而是返回一个副本,但是环境可以变得非常大,包含许多包含更多内容的容器,并且复制所有这些都很昂贵

除了指导任何直接共享以及通过套接字或管道进行交谈之外,这些似乎是我的选择,尽管我无法决定选择哪一个。

哪个是我最好的选择?我没有考虑过什么选择可能对我有帮助?

1 个答案:

答案 0 :(得分:0)

这个问题基于意见,但根据过去的经验,我建议使用copy-on-write。您可以在顶层执行此操作,复制整个对象,或者您可以逐个执行此操作,这可能会解决复制的开销。例如:

struct BigData;
struct Shared
{
    std::shared_ptr<const BigData> a;
    std::shared_ptr<const BigData> b;
    std::shared_ptr<const BigData> c;
}

然后,您只需复制您修改的部分,并通过Shared的副本发送到插件。因此,如果您更改了a中的内容,bc仍会指向同一个对象,但a会指向从中复制的新BigData原件然后修改。