#ifndef IN_OUT_INTERFACE_H #define IN_OUT_INTERFACE_H #include #include #include #include #include namespace pacpus { template class InputInterface : public InputInterfaceBase { public: typedef T data_type; typedef C component_type; typedef void (C::*process_data_function_type)(const T &); InputInterface(QString name, C * component, process_data_function_type processMethod) : InputInterfaceBase(name, component, component) , method(processMethod) { } ~InputInterface() { } std::size_t getDataSize() const { return sizeof(T); } const std::type_info & getDataType() const { return typeid(T); } // FIXME: what's the purpose of this function? //PacpusEvent * getEventTemplate() //{ // return new PacpusTypedEvent(TYPED_EVENT); //} // FIXME: what's the purpose of this function? void customEvent(QEvent * event) { // check that component has been started if ((NULL == getComponent()) || (!getComponent()->isActive())) { LOG_DEBUG("component is not active"); return; } LOG_TRACE("Receiver: " << getSignature()); //PacpusTypedEvent * typedEvent = dynamic_cast *>(event); PacpusEvent * pacpusEvent = dynamic_cast(event); if (!pacpusEvent) { LOG_WARN("dynamic_cast failed: not a PacpusEvent"); return; } PacpusTypedEvent * typedEvent = dynamic_cast *>(pacpusEvent); if (!typedEvent) { LOG_WARN("dynamic_cast failed: incompatible event types"); return; } switch (event->type()) { case TYPED_EVENT: if (TimeBounded == readingMode() && typedEvent->timerange() < 500) { LOG_WARN("Incorrect TimeRange (0), switch to NeverSkip"); readingMode() = NeverSkip; } switch (readingMode()) { case TimeBounded: if (road_time() - typedEvent->time() > typedEvent->timerange()) { LOG_TRACE("Data skipped, receiver: " << this->getSignature()); break; } (dynamic_cast(component())->*method)(typedEvent->data()); break; case GetLast: (dynamic_cast(component())->*method)(typedEvent->data()); // delete all remaining events QCoreApplication::removePostedEvents(this, TYPED_EVENT); break; case NeverSkip: (dynamic_cast(component())->*method)(typedEvent->data()); break; default: LOG_WARN("Unknown reading mode " << readingMode()); break; } break; // Add here new event type if needed default: LOG_WARN("Unknown event ID " << event->type()); break; } event->accept(); } // TODO for Pulling mode (not yet implemented !!!) T & getData() { T data; // TODO ask output data; return data; } protected: process_data_function_type method; }; template class OutputInterface : public OutputInterfaceBase { public: typedef T data_type; typedef C component_type; OutputInterface(QString name, C * component) : OutputInterfaceBase(name, component, component) {} ~OutputInterface() {} /// Send data through a typed output void send(const T & data, road_time_t t = road_time(), road_timerange_t tr = 0); std::size_t getDataSize() const { return sizeof(T); } const std::type_info & getDataType() const { return typeid(T); } }; template void OutputInterface::send(const T & data, road_time_t t, road_timerange_t tr) { // FIXME Data Shared //QSharedPointer sharedPointer = new T(data); for (QList::iterator it = connections().begin(), itend = connections().end(); it != itend; ++it) { // Qt documentatino: // The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted. // It is not safe to access the event after it has been posted. QEvent * newEvent = new PacpusTypedEvent(TYPED_EVENT, data, t, tr); QCoreApplication::postEvent( it->getInterface(), newEvent, it->getPriority() ); LOG_TRACE("Sender: " << it->getInterface()->getSignature()); } } template bool checkedSend(OutputInterface * sender, const T2 & data, road_time_t t = road_time(), road_timerange_t tr = 0); template bool checkedSend(OutputInterface * sender, const T2 & data, road_time_t t, road_timerange_t tr) { if (sender && sender->hasConnection()) { sender->send(data, t, tr); return true; } return false; } } // namespace pacpus #endif // IN_OUT_INTERFACE_H