Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';“这是一种得到两个”的模式;“深”;多线程程序的各个部分相互对话?_C++_Multithreading_Design Patterns_Plugins_Refactoring - Fatal编程技术网

C++ 什么';“这是一种得到两个”的模式;“深”;多线程程序的各个部分相互对话?

C++ 什么';“这是一种得到两个”的模式;“深”;多线程程序的各个部分相互对话?,c++,multithreading,design-patterns,plugins,refactoring,C++,Multithreading,Design Patterns,Plugins,Refactoring,我在设计、重构或“分类”方面有一个普遍的问题: 我有一个现有的多线程C++应用程序,它使用多个插件库搜索数据。在当前的搜索接口中,给定的插件接收一个搜索字符串和一个指向QList对象的指针。该插件在不同的线程上运行,它会出去搜索各种数据源(本地和网络),并将感兴趣的对象添加到列表中。当插件返回时,主程序仍然在单独的线程上,将该数据添加到本地数据存储(进一步处理),使用互斥锁保护该插入点。因此,每个插件都可以异步返回数据 QT-base插件库基于消息传递。有相当数量的插件已经为应用程序编写和测试,

我在设计、重构或“分类”方面有一个普遍的问题:

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

QT-base插件库基于消息传递。有相当数量的插件已经为应用程序编写和测试,它们工作得相当好

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

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

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

  • 加载插件时,传递它们 指向我的“目录”的指针 开始这就变成了一个额外的, 新系统的“不可见”界面 插件。这似乎很快,很容易, 根据OO完全错误,但是 我看不出未来会有什么问题

  • 将方法/消息添加到 现有的接口,所以我有一个 第二个功能可以是 需要新的插件库, 该消息将传递指向的指针 将目录添加到插件。这 对于插件来说很容易,但是 会使我的主代码和 看起来总的来说很糟糕

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

  • 所以,我的问题是

    有人能告诉我选项1的具体危险吗

    B.是否有一种已知的模式适合这种问题

    Edit1:

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

    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);
        }
    }
    
    其他地方(规范){
    QList结果;
    插件->获取结果(规范和结果);
    使用列表(结果);
    }
    ...
    void PluginHandler::getResults(QString*spec,QList*results)
    {
    如果(id->count()==0)返回;
    foreach(PluginInfo信息,插件){
    如果(信息已加载)
    info.obj->msg(msg_GET_RESULTS,(void*)spec,(void*)RESULTS);
    }
    }
    

    这是一个重复的代码。我宁愿把它延长也不愿把它弄坏

    那么,选项1最终是选项3。您正在重新设计插件API以从主应用程序接收额外数据

    这是一个简单的重新设计,只要“目录”得到很好的实现,并且隐藏了哈希和互斥备份存储的每个实现细节,它就不坏,并且可以很好地达到目的


    现在,如果目录泄漏了实施细节,那么您最好使用消息查询商店,接收带有所需数据的响应。

    对不起,我刚刚将您的问题重读了3遍,我认为我的答案可能太简单了

    您的“目录”是一个独立的对象吗?如果没有,可以将其包装为自己的对象。目录应该是完全安全的(包括线程安全的)——或者更好的是不可变的

    这样,将目录传递给新插件将是非常有效的OO。如果您担心通过许多层传递它们,可以为目录创建工厂

    抱歉,如果我仍然误解了什么,但我不认为这种方法有任何错误。但是,如果您的目录是您无法控制的对象,例如数据库对象或集合,那么您必须将其封装在可以使用漂亮、干净的界面进行控制的内容中

    如果您的目录在您的程序中被许多部分使用,您可以查看一个工厂(最简单的情况是,它退化为一个单件)。使用工厂,你应该能够用目录调用你的目录;或者别的什么。这样,你就可以把同样的东西送给每个想要的人,而不需要传递

    (顺便说一句,这与singleton非常相似,但将其编码为工厂会提醒您,几乎肯定会有不止一个——还要记住允许Catalog.setType(“衣服”)进行测试。

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

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


    如果您认为它是不好的OO,那么这是因为您从根本上试图做什么(违反应用程序的基本架构),而不是您如何做

    嗯,目录是插件中的一个全局变量,插件接口并不能让你很明显地访问目录,但除此之外……但是目录的作用是什么