Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Fregloin от Август 01, 2013, 10:21



Название: Как отправить наследника QEvent в несколько объектов в разных потоках?
Отправлено: Fregloin от Август 01, 2013, 10:21
Привет. Есть приложение, в котором множество объектов в разных потоках. Нужно что бы эти объекты могли общаться между собою.
Объекты связываются между собой по тегу, допустим простро строки. Нужно написать свой диспетчер событий, который будет заниматься перенаправлением QEvent из отправителя получателям ( от 1-го до N) в разных потоках. Связи кто кому отправляет задаются заранее, хотя должна быть возможность динамического связывания.
Раньше я слал конкретным потокам события через QCoreApplication::postEvent, но там была связь 1 к 1. В документации написано, что событие нужно создавать в куче, слать через postEvent, после чего очередь его сама удалит. Вопрос, а когда она удалит это событие? Когда его обработает первый приемник?

Вот мои наброски диспетчера

Рассматриваем CInterfaceTag как QString(хотя на самом деле это набор из нескольких строк).

Код:
#include <QObject>
#include <QHash>
#include "csharedobjectinterface.h"
#include "cxmldocumentiteminterface.h"
#include "ctaggedinterface.h"

class   CAbstractEvent;
class   CAbstractArmLogic;

class CEventProxy : public QObject, public CSharedObjectInterface, public CXMLDocumentItemInterface
{
Q_OBJECT

    QHash<CInterfaceTag, QObject*>              fsubscribedObjects; //подписчики на события
    QHash<CInterfaceTag, QList<CInterfaceTag> > freceivers;         //приемники

public:

    explicit    CEventProxy(QObject *parent = 0);

    void        subscribeObjectForEventReceiving(const CInterfaceTag & address, QObject * InterfaceObject);  //подписывает объект на приём событий
    void        unsubscribeObjectFromEventReceiving(const CInterfaceTag & address);   //отписывает объект по адерсу
    void        unsubscribeObjectFromEventReceiving(QObject *InterfaceObject);    //отписывает объект по интерфейсу

    void        loadFromDocument(QDomDocument &doc, QDomElement &node);
    void        saveToDocument(QDomDocument &doc, QDomElement &node);
    void        afterDocumentLoad();
    void        clearDocument();

    void        applyReceiversList(const QHash<CInterfaceTag, QList<CInterfaceTag> > & receivers);
    void        getReceiversList(QHash<CInterfaceTag, QList<CInterfaceTag> > & receivers);

    inline      QList<QObject*> subscribedObjects() { return    fsubscribedObjects.values();    }

public  slots:

    void        sendEvent(const CAbstractEvent & event);  //отправка события

};

Код:
#include <QCoreApplication>
#include "ceventproxy.h"
#include "cabstractevent.h"

CEventProxy::CEventProxy(QObject *parent) :
    QObject(parent),CSharedObjectInterface(),CXMLDocumentItemInterface()
{

}

void CEventProxy::sendEvent(const CAbstractEvent &event)
{
    QList<CInterfaceTag>    destinationTags = freceivers.value(event.eventTag());
    if(!destinationTags.isEmpty())
    {
        QObject                 *   interfaceObject;
        CAbstractEvent  *   eventPtr = new CAbstractEvent(QEvent::Type(ABSTRACT_EVENT_TYPE));
        *eventPtr = event;
        foreach (const CInterfaceTag & destinationTag, destinationTags)
        {
            if((interfaceObject=fsubscribedObjects.value(destinationTag,NULL)))
            {
                QCoreApplication::postEvent(interfaceObject,eventPtr);
            }
        }
    }
}

void CEventProxy::subscribeObjectForEventReceiving(const CInterfaceTag &address, QObject *InterfaceObject)
{
    if(!address.isValid() || !InterfaceObject)   return;
    fsubscribedObjects[address] = InterfaceObject;
}

void CEventProxy::unsubscribeObjectFromEventReceiving(const CInterfaceTag &address)
{
    fsubscribedObjects.remove(address);
}

void CEventProxy::unsubscribeObjectFromEventReceiving(QObject *InterfaceObject)
{
    for(QHash<CInterfaceTag, QObject*>::iterator it = fsubscribedObjects.begin(); it!= fsubscribedObjects.end(); it++)
    {
        if(it.value() == InterfaceObject)
        {
            unsubscribeObjectFromEventReceiving(it.key());
            break;
        }
    }
}

//остальное не интересно