Привет. Есть приложение, в котором множество объектов в разных потоках. Нужно что бы эти объекты могли общаться между собою.
Объекты связываются между собой по тегу, допустим простро строки. Нужно написать свой диспетчер событий, который будет заниматься перенаправлением 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;
}
}
}
//остальное не интересно