Проблемы с вложенным объектом в функциональный объект tbb::flow::graph

У меня есть функциональный объект, который я использую как тело для multifunction_node:

class module
{
private:
    bool valid;

    QString description;

    bool hasDetectionBranch;
    tDataDescription bufData;

    void* dllObject; //<-- This is a pointer to an object constructed with help of the external dll

    qint64 TimeOut;

public:

    module(const QString& _ExtLibName);
    virtual ~module();

    void operator() (pTransmitData _transmitData, multi_node::output_ports_type &op);
};

«dllObject» создается во время создания объекта «модуль»:

module::module(const QString& _ExtLibName) :
    valid(true), hasDetectionBranch(false)
{
    GetObjectDescription = (tGetObjectDescription)QLibrary::resolve(_ExtLibName, "GetObjectDescription");
    CreateObject = (tCreateObject)QLibrary::resolve(_ExtLibName, "CreateObject");
    DestroyObject = (tDestroyObject)QLibrary::resolve(_ExtLibName, "DestroyObject");

    if (!CreateObject || !DestroyObject || !GetObjectDescription)
        valid = false;
    else
    {
        description = QString(GetObjectDescription());
        dllObject = CreateObject();
    }
}

И это когда 'dllObject' уничтожается:

module::~module()
{
    if (valid)
    {
        DestroyObject(dllObject);
    }
}

Я построил небольшой график:

void MainWindow::goBabyClicked(void)
{
    module mod(QString("my.dll")); //<-- Here is OK and mod.dllObject is correct
    if (!mod.isValid())
    {
        qDebug() << "mod is invalid!\n";
        return;
    }

    first fir(input);
    folder fol(QString("C:/out"), 10000);

    graph g;

    source_node<pTransmitData> src(g, fir, false);

    multi_node mnode(g, tbb::flow::serial, mod); //<-- WTF? ~module() is executed!

    function_node<pTransmitData> f(g, tbb::flow::serial, fol);

    make_edge(src, mnode);
    make_edge(mnode, f);

    src.activate();

    g.wait_for_all();
}

Итак, у меня есть 2 вопроса: 1) Почему выполняется ~module() и как это предотвратить? 2) Как правильно сохранить указатель на вложенный объект?

ОБНОВЛЕНИЕ Добавлен фиктивный код для предотвращения уничтожения dllObject в первый раз, например:

bool b = false;
module::~module()
{
    if (valid && b)
    {
        DestroyObject(dllObject);
    }
    if (!b)
        b = true;
    valid = false;
}

Теперь он работает как положено, но выглядит некрасиво :/


person Max Pashkov    schedule 30.10.2015    source источник
comment
Что такое multi_node? Я не знаком с TBB Flow Graph, но пытался его найти. Класс с самым близким именем, которое я нашел, было multifunction_node...   -  person James Adkison    schedule 30.10.2015


Ответы (1)


Максимум,

Я предполагаю, что у вас есть typedef из multi_node, который похож на пример из справочного руководства.

Конструктор для multifunction_node имеет следующую подпись:

multifunction_node( graph &g, size_t concurrency, Body body );

Объект body копируется при передаче параметров, а также при построении узла, поэтому при построении создается две копии mod (на самом деле три, так как исходная копия тела также сохраняется для повторной инициализации тела при вызове reset() с rf_reset_bodies). Вызовы деструктора, которые вы видите, вероятно, используются для уничтожения копий.

Объект body также должен иметь определенный конструктор копирования или иметь возможность принимать конструктор копирования по умолчанию для создания копий тела. Я думаю, что QString имеет определенный конструктор копирования, но я не знаю о таких полях, как tDataDescription. (Я думал, что мы рассмотрели основные требования к объектам Body в Справочном руководстве, но я все еще ищу этот раздел.) В любом случае класс Body должен быть CopyConstructible, так как он копируется несколько раз.

С уважением, Крис

person cahuson    schedule 31.10.2015
comment
Майк нашел ссылку; это находится в Справочном руководстве, в разделе Flow Graph, на странице multifunction_node с требованиями к телу. Это повторяется для continue_node, function_node и source_node, узлов, которые используют Body. - person cahuson; 04.11.2015