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

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

Major: cleaned connection interfaces.

  • Property svn:executable set to *
File size: 5.3 KB
Line 
1#ifndef IN_OUT_INTERFACE_H
2#define IN_OUT_INTERFACE_H
3
4#include <Pacpus/kernel/InputOutputBase.h>
5#include <Pacpus/kernel/Log.h>
6
7#include <QByteArray>
8#include <QCoreApplication>
9#include <typeinfo>
10
11namespace pacpus {
12
13template <typename T, class C>
14class InputInterface
15 : public InputInterfaceBase
16{
17public:
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)
23 : InputInterfaceBase(name, component, component)
24 , method(processMethod)
25 {
26 }
27
28 ~InputInterface()
29 {
30 }
31
32 std::size_t getDataSize() const
33 {
34 return sizeof(T);
35 }
36
37 const std::type_info & getDataType() const
38 {
39 return typeid(T);
40 }
41
42 // FIXME: what's the purpose of this function?
43 //PacpusEvent * getEventTemplate()
44 //{
45 // return new PacpusTypedEvent<T>(TYPED_EVENT);
46 //}
47
48 // FIXME: what's the purpose of this function?
49 void customEvent(QEvent * event)
50 {
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
71 switch (event->type()) {
72 case TYPED_EVENT:
73 if (TimeBounded == readingMode() && typedEvent->timerange() < 500) {
74 LOG_WARN("Incorrect TimeRange (0), switch to NeverSkip");
75 readingMode() = NeverSkip;
76 }
77
78 switch (readingMode()) {
79 case TimeBounded:
80 if (road_time() - typedEvent->time() > typedEvent->timerange()) {
81 LOG_TRACE("Data skipped, receiver: " << this->getSignature());
82 break;
83 }
84
85 (dynamic_cast<C*>(component())->*method)(typedEvent->data());
86 break;
87
88 case GetLast:
89 (dynamic_cast<C*>(component())->*method)(typedEvent->data());
90 // delete all remaining events
91 QCoreApplication::removePostedEvents(this, TYPED_EVENT);
92 break;
93
94 case NeverSkip:
95 (dynamic_cast<C*>(component())->*method)(typedEvent->data());
96 break;
97
98 default:
99 LOG_WARN("Unknown reading mode " << readingMode());
100 break;
101 }
102 break;
103
104 // Add here new event type if needed
105
106 default:
107 LOG_WARN("Unknown event ID " << event->type());
108 break;
109 }
110 event->accept();
111 }
112
113 // TODO for Pulling mode (not yet implemented !!!)
114 T & getData()
115 {
116 T data;
117 // TODO ask output data;
118 return data;
119 }
120
121protected:
122 process_data_function_type method;
123};
124
125template <typename T, class C>
126class OutputInterface
127 : public OutputInterfaceBase
128{
129public:
130 typedef T data_type;
131 typedef C component_type;
132
133 OutputInterface(QString name, C * component)
134 : OutputInterfaceBase(name, component, component)
135 {}
136
137 ~OutputInterface()
138 {}
139
140 /// Send data through a typed output
141 void send(const T & data, road_time_t t = road_time(), road_timerange_t tr = 0);
142
143 std::size_t getDataSize() const
144 {
145 return sizeof(T);
146 }
147
148 const std::type_info & getDataType() const
149 {
150 return typeid(T);
151 }
152};
153
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
160 for (QList<ConnectionBase>::iterator it = connections().begin(), itend = connections().end(); it != itend; ++it) {
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);
165 QCoreApplication::postEvent(
166 it->getInterface(),
167 newEvent,
168 it->getPriority()
169 );
170 LOG_DEBUG("Sender: " << it->getInterface()->getSignature());
171 LOG_DEBUG("Data &: " << &data);
172 }
173}
174
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
188} // namespace pacpus
189
190#endif // IN_OUT_INTERFACE_H
Note: See TracBrowser for help on using the repository browser.