source: pacpusframework/trunk/include/Pacpus/kernel/InputOutputInterface.h@ 253

Last change on this file since 253 was 206, checked in by Marek Kurdej, 11 years ago

Major: cleaned connection interfaces.

  • Property svn:executable set to *
File size: 5.3 KB
RevLine 
[89]1#ifndef IN_OUT_INTERFACE_H
2#define IN_OUT_INTERFACE_H
3
[199]4#include <Pacpus/kernel/InputOutputBase.h>
[95]5#include <Pacpus/kernel/Log.h>
[199]6
[153]7#include <QByteArray>
[200]8#include <QCoreApplication>
[110]9#include <typeinfo>
[89]10
11namespace pacpus {
12
[152]13template <typename T, class C>
[148]14class InputInterface
15 : public InputInterfaceBase
[89]16{
17public:
[199]18 typedef T data_type;
19 typedef C component_type;
20 typedef void (C::*process_data_function_type)(const T &);
21
22 InputInterface(QString name, C * component, process_data_function_type processMethod)
[152]23 : InputInterfaceBase(name, component, component)
[199]24 , method(processMethod)
[206]25 {
26 }
[89]27
[148]28 ~InputInterface()
[206]29 {
30 }
[89]31
[199]32 std::size_t getDataSize() const
[148]33 {
34 return sizeof(T);
35 }
[89]36
[199]37 const std::type_info & getDataType() const
[148]38 {
[199]39 return typeid(T);
[148]40 }
[96]41
[199]42 // FIXME: what's the purpose of this function?
[206]43 //PacpusEvent * getEventTemplate()
44 //{
45 // return new PacpusTypedEvent<T>(TYPED_EVENT);
46 //}
[148]47
[199]48 // FIXME: what's the purpose of this function?
[184]49 void customEvent(QEvent * event)
[148]50 {
[206]51 // check that component has been started
52 if ((NULL == getComponent()) || (!getComponent()->isActive())) {
53 LOG_DEBUG("component is not active");
54 return;
55 }
56
57 LOG_DEBUG("Receiver: " << getSignature());
58
59 //PacpusTypedEvent<T> * typedEvent = dynamic_cast<PacpusTypedEvent<T> *>(event);
60 PacpusEvent * pacpusEvent = dynamic_cast<PacpusEvent *>(event);
61 if (!pacpusEvent) {
62 LOG_WARN("dynamic_cast failed: not a PacpusEvent");
63 return;
64 }
65 PacpusTypedEvent<T> * typedEvent = dynamic_cast<PacpusTypedEvent<T> *>(pacpusEvent);
66 if (!typedEvent) {
67 LOG_WARN("dynamic_cast failed: incompatible event types");
68 return;
69 }
70
[89]71 switch (event->type()) {
[148]72 case TYPED_EVENT:
[206]73 if (TimeBounded == readingMode() && typedEvent->timerange() < 500) {
[153]74 LOG_WARN("Incorrect TimeRange (0), switch to NeverSkip");
75 readingMode() = NeverSkip;
76 }
[110]77
[148]78 switch (readingMode()) {
[110]79 case TimeBounded:
[148]80 if (road_time() - typedEvent->time() > typedEvent->timerange()) {
[206]81 LOG_TRACE("Data skipped, receiver: " << this->getSignature());
[148]82 break;
83 }
[110]84
[148]85 (dynamic_cast<C*>(component())->*method)(typedEvent->data());
[89]86 break;
[110]87
88 case GetLast:
[148]89 (dynamic_cast<C*>(component())->*method)(typedEvent->data());
[153]90 // delete all remaining events
91 QCoreApplication::removePostedEvents(this, TYPED_EVENT);
[110]92 break;
93
94 case NeverSkip:
[159]95 (dynamic_cast<C*>(component())->*method)(typedEvent->data());
96 break;
[110]97
98 default:
[159]99 LOG_WARN("Unknown reading mode " << readingMode());
[206]100 break;
[89]101 }
[110]102 break;
[89]103
[184]104 // Add here new event type if needed
[89]105
[110]106 default:
[153]107 LOG_WARN("Unknown event ID " << event->type());
[110]108 break;
[89]109 }
[206]110 event->accept();
[110]111 }
[89]112
[159]113 // TODO for Pulling mode (not yet implemented !!!)
[206]114 T & getData()
115 {
[110]116 T data;
117 // TODO ask output data;
118 return data;
[89]119 }
120
121protected:
[199]122 process_data_function_type method;
[89]123};
124
[152]125template <typename T, class C>
[185]126class OutputInterface
127 : public OutputInterfaceBase
[89]128{
129public:
[199]130 typedef T data_type;
131 typedef C component_type;
132
[184]133 OutputInterface(QString name, C * component)
[185]134 : OutputInterfaceBase(name, component, component)
[184]135 {}
[89]136
[199]137 ~OutputInterface()
138 {}
139
[206]140 /// Send data through a typed output
[184]141 void send(const T & data, road_time_t t = road_time(), road_timerange_t tr = 0);
142
[199]143 std::size_t getDataSize() const
[148]144 {
145 return sizeof(T);
146 }
147
[199]148 const std::type_info & getDataType() const
[148]149 {
[199]150 return typeid(T);
[148]151 }
[89]152};
153
[185]154template <typename T, class C>
155void OutputInterface<T, C>::send(const T & data, road_time_t t, road_timerange_t tr)
156{
157 // FIXME Data Shared
158 //QSharedPointer<T> sharedPointer = new T(data);
159
[200]160 for (QList<ConnectionBase>::iterator it = connections().begin(), itend = connections().end(); it != itend; ++it) {
[202]161 // Qt documentatino:
162 // 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.
163 // It is not safe to access the event after it has been posted.
164 QEvent * newEvent = new PacpusTypedEvent<T>(TYPED_EVENT, data, t, tr);
[206]165 QCoreApplication::postEvent(
166 it->getInterface(),
167 newEvent,
168 it->getPriority()
169 );
[202]170 LOG_DEBUG("Sender: " << it->getInterface()->getSignature());
171 LOG_DEBUG("Data &: " << &data);
[185]172 }
173}
174
[202]175template <typename T1, typename T2, class C>
176bool checkedSend(OutputInterface<T1, C> * sender, const T2 & data, road_time_t t = road_time(), road_timerange_t tr = 0);
177
178template <typename T1, typename T2, class C>
179bool checkedSend(OutputInterface<T1, C> * sender, const T2 & data, road_time_t t, road_timerange_t tr)
180{
181 if (sender && sender->hasConnection()) {
182 sender->send(data, t, tr);
183 return true;
184 }
185 return false;
186}
187
[89]188} // namespace pacpus
189
190#endif // IN_OUT_INTERFACE_H
Note: See TracBrowser for help on using the repository browser.