c++ - 让多线程程序的两个 "deep"部分相互通信的模式是什么?

标签 c++ multithreading design-patterns plugins refactoring

我在设计、重构或“分类”方面遇到了这个普遍问题:

我有一个现有的多线程 C++ 应用程序,它使用许多插件库搜索数据。使用当前的搜索接口(interface),给定的插件接收搜索字符串和指向 QList 对象的指针。该插件在不同的线程上运行,并搜索各种数据源(本地和网络上)并将感兴趣的对象添加到列表中。当插件返回时,主程序仍然在单独的线程上,将此数据添加到本地数据存储(进行进一步处理),并使用互斥体保护此插入点。因此每个插件都可以异步返回数据。

基于 QT 的插件库基于消息传递。有相当多的插件已经为应用程序编写和测试过,并且运行得相当好。

我想编写更多插件并利用现有的应用程序。

问题是新插件需要来自应用程序的更多信息。他们在搜索时需要间歇性地访问本地数据存储本身。因此,为了实现这一点,他们需要直接或间接访问存储数据的哈希数组和保护对存储的多次访问的互斥锁。我假设通过在“目录”对象中添加额外的方法来封装访问。

我可以看到三种编写这些新插件的方法。

  1. 加载插件时,传递它们 指向我的“目录”的指针 开始。这成为一个额外的, 新的“隐形”界面 插件。这看起来又快又简单, 根据 OO 完全错误,但是 我看不到 future 会出现什么问题。

  2. 将方法/消息添加到 现有的接口(interface),所以我有一个 第二个函数可以是 需要新的插件库, 该消息将传递一个指针 插件目录。这 对于插件来说很容易,但它 会使我的主要代码复杂化并且 看起来总体很糟糕。

  3. 重新设计插件界面。 根据 OO 的说法,这似乎是“最好的”, 可能还有其他额外的好处,但是 需要各种 重写。

所以,我的问题是

A.谁能告诉我选项 1 的具体危险吗?

B.是否有适合此类问题的已知模式?

编辑1:

调用插件例程的典型函数如下所示:

elsewhere(spec){
    QList<CatItem> results;
    plugins->getResult(spec, &results);
    use_list(results);
}

...
void PluginHandler::getResults(QString* spec, QList<CatItem>* results)
{
    if (id->count() == 0) return;
    foreach(PluginInfo info, plugins) {
        if (info.loaded)
            info.obj->msg(MSG_GET_RESULTS, (void*) spec, (void*) results);
    }
}

这是一段重复的代码。我宁愿延长它,也不愿破坏它。

最佳答案

为什么“根据 OO 是完全错误的”?如果您的插件需要访问该对象,并且它不违反您想要保留的任何抽象,那么它就是正确的解决方案。

对我来说,当你决定你的插件需要访问列表本身时,你似乎就搞砸了你的抽象。你刚刚炸毁了整个应用程序的架构。您确定需要访问实际列表本身吗?为什么?你需要从中得到什么?能否以更合理的方式提供这些信息?一种不会 1) 增加对共享资源的争用(并增加微妙的多线程错误(如竞争条件和死锁)的风险),2) 不会破坏应用程序其余部分的架构(特别保留了分离)列表与其客户端之间,以允许异步)

如果您认为它是糟糕的面向对象,那么这是因为您从根本上尝试执行的操作(违反了应用程序的基本架构),而不是您执行此操作的方式。

关于c++ - 让多线程程序的两个 "deep"部分相互通信的模式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1891249/

相关文章:

c++ - 非法引用非静态成员...typedef?

c++ - 无法在 C++ Visual Studio 中编译 C 文件

c++ - std::vector 的不完整类型

java - Android/Java多线程-线程直到主线程完成工作才继续

php - 如果数据库丢失,设计模式可以优雅地失败

javascript - 如何仅在多个其他功能完成后才执行 Javascript 功能?

c++ - CLOCK_THREAD_CPUTIME_ID 在 MacOS 上

java - 同步静态方法和静态方法内的同步块(synchronized block)之间的区别?

android - 如何确定性地使用 std::this_thread::yield() ?

Java:可变参数声明的构造函数