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

Last change on this file since 273 was 273, checked in by Marek Kurdej, 10 years ago

Formatting: changed "\t" to " " (4 spaces).

  • Property svn:executable set to *
File size: 8.1 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 <boost/function.hpp>
8#include <QByteArray>
9#include <QCoreApplication>
10#include <typeinfo>
11
12namespace pacpus {
13
14template <typename T, class C>
15class InputInterface
16 : public InputInterfaceBase
17{
18public:
19 typedef T data_type;
20 typedef C component_type;
21 typedef void (C::*process_data_function_type_with_event)(T&, PacpusEvent);
22 typedef void (C::*process_data_function_type)(T&);
23 typedef void (C::*process_const_data_function_type_with_event)(T const&, PacpusEvent);
24 typedef void (C::*process_const_data_function_type)(T const&);
25 //typedef boost::function<void (C*, T&, PacpusEvent)> process_data_function_type_with_event;
26 //typedef boost::function<void (C*, T&)> process_data_function_type;
27 //typedef boost::function<void (C*, T const&, PacpusEvent)> process_const_data_function_type_with_event;
28 //typedef boost::function<void (C*, T const&)> process_const_data_function_type;
29
30 InputInterface(QString name, C* component, process_data_function_type_with_event processingMethod)
31 : InputInterfaceBase(name, component, component)
32 {
33 mProcessingMethod.fe = processingMethod;
34 }
35
36 InputInterface(QString name, C* component, process_data_function_type processingMethod)
37 : InputInterfaceBase(name, component, component)
38 {
39 mProcessingMethod.f = processingMethod;
40 }
41
42 InputInterface(QString name, C* component, process_const_data_function_type_with_event processingMethod)
43 : InputInterfaceBase(name, component, component)
44 {
45 mProcessingMethod.cfe = processingMethod;
46 }
47
48 InputInterface(QString name, C* component, process_const_data_function_type processingMethod)
49 : InputInterfaceBase(name, component, component)
50 {
51 mProcessingMethod.cf = processingMethod;
52 }
53
54 ~InputInterface()
55 {
56 }
57
58 std::size_t getDataSize() const
59 {
60 return sizeof(T);
61 }
62
63 std::type_info const& getDataType() const
64 {
65 return typeid(T);
66 }
67
68 // FIXME: what's the purpose of this function?
69 //PacpusEvent * getEventTemplate()
70 //{
71 // return new PacpusTypedEvent<T>(TYPED_EVENT);
72 //}
73
74 // FIXME: what's the purpose of this function?
75 void customEvent(QEvent* event)
76 {
77 static road_timerange_t const kMaximumBoundedTimeRange = 500;
78
79 if (!event) {
80 LOG_WARN("null event");
81 return;
82 }
83
84 // check that component has been started
85 if ((NULL == getComponent()) || (!getComponent()->isActive())) {
86 LOG_DEBUG("component is not active");
87 return;
88 }
89
90 LOG_TRACE("Receiver: " << getSignature());
91
92 //PacpusTypedEvent<T>* typedEvent = dynamic_cast<PacpusTypedEvent<T> *>(event);
93 PacpusEvent* pacpusEvent = dynamic_cast<PacpusEvent*>(event);
94 if (!pacpusEvent) {
95 LOG_WARN("dynamic_cast failed: not a PacpusEvent");
96 return;
97 }
98 PacpusTypedEvent<T>* typedEvent = dynamic_cast<PacpusTypedEvent<T>*>(pacpusEvent);
99 if (!typedEvent) {
100 LOG_WARN("dynamic_cast failed: incompatible event types");
101 return;
102 }
103
104 switch (event->type()) {
105 case TYPED_EVENT:
106 if (TimeBounded == readingMode() && typedEvent->timerange() < kMaximumBoundedTimeRange) {
107 LOG_WARN("Incorrect TimeRange (< " << kMaximumBoundedTimeRange << "), switching to NeverSkip mode");
108 readingMode() = NeverSkip;
109 }
110
111 switch (readingMode()) {
112 case TimeBounded:
113 if (road_time() - typedEvent->time() > typedEvent->timerange()) {
114 LOG_TRACE("Data skipped, receiver: " << this->getSignature());
115 break;
116 }
117
118 mProcessingMethod.invoke(component(), typedEvent->data(), *typedEvent);
119 break;
120
121 case GetLast:
122 mProcessingMethod.invoke(component(), typedEvent->data(), *typedEvent);
123
124 // delete all remaining events
125 QCoreApplication::removePostedEvents(this, TYPED_EVENT);
126 break;
127
128 case NeverSkip:
129 mProcessingMethod.invoke(component(), typedEvent->data(), *typedEvent);
130 break;
131
132 default:
133 LOG_WARN("Unknown reading mode " << readingMode());
134 break;
135 }
136 break;
137
138 // Add here new event type if needed
139
140 default:
141 LOG_WARN("Unknown event ID " << event->type());
142 break;
143 }
144 event->accept();
145 }
146
147 // TODO: pull mode (NOT YET IMPLEMENTED!!!)
148 T& getData()
149 {
150 T data;
151 // TODO: ask the output data;
152 return data;
153 }
154
155protected:
156 struct ProcessingMethod
157 {
158 ProcessingMethod()
159 {
160 fe = NULL;
161 f = NULL;
162 cfe = NULL;
163 cf = NULL;
164 }
165
166 void invoke(ComponentBase* component, T& data, PacpusEvent event)
167 {
168 C* comp = dynamic_cast<C*>(component);
169 if (NULL == comp) {
170 LOG_WARN("NULL component");
171 return;
172 }
173 //if (fe) {
174 // fe(comp, data, event);
175 //} else if (f) {
176 // f(comp, data);
177 //} else if (cfe) {
178 // cfe(comp, data, event);
179 //} else if (cf) {
180 // cf(comp, data);
181 //} else {
182 // LOG_WARN("no method to invoke");
183 //}
184 if (fe) {
185 (comp->*fe)(data, event);
186 } else if (f) {
187 (comp->*f)(data);
188 } else if (cfe) {
189 (comp->*cfe)(data, event);
190 } else if (cf) {
191 (comp->*cf)(data);
192 } else {
193 LOG_WARN("no method to invoke");
194 }
195 }
196
197 process_data_function_type_with_event fe;
198 process_data_function_type f;
199 process_const_data_function_type_with_event cfe;
200 process_const_data_function_type cf;
201 };
202
203 ProcessingMethod mProcessingMethod;
204};
205
206template <typename T, class C>
207class OutputInterface
208 : public OutputInterfaceBase
209{
210public:
211 typedef T data_type;
212 typedef C component_type;
213
214 OutputInterface(QString name, C* component)
215 : OutputInterfaceBase(name, component, component)
216 {}
217
218 ~OutputInterface()
219 {}
220
221 /// Send data through a typed output
222 void send(T const& data, road_time_t t = road_time(), road_timerange_t tr = 0);
223
224 std::size_t getDataSize() const
225 {
226 return sizeof(T);
227 }
228
229 std::type_info const& getDataType() const
230 {
231 return typeid(T);
232 }
233};
234
235template <typename T, class C>
236void OutputInterface<T, C>::send(T const& data, road_time_t t, road_timerange_t tr)
237{
238 // FIXME: use shared data
239 //QSharedPointer<T> sharedPointer = new T(data);
240
241 for (QList<ConnectionBase>::iterator it = connections().begin(), itend = connections().end(); it != itend; ++it) {
242 // Qt documentation:
243 // 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.
244 // It is not safe to access the event after it has been posted.
245 QEvent* pacpusEvent = new PacpusTypedEvent<T>(TYPED_EVENT, data, t, tr);
246 QCoreApplication::postEvent(
247 it->getInterface(),
248 pacpusEvent,
249 it->getPriority()
250 );
251 LOG_TRACE("Sender: " << it->getInterface()->getSignature());
252 }
253}
254
255template <typename T1, typename T2, class C>
256bool checkedSend(OutputInterface<T1, C>* sender, T2 const& data, road_time_t t = road_time(), road_timerange_t tr = 0);
257
258template <typename T1, typename T2, class C>
259bool checkedSend(OutputInterface<T1, C>* sender, T2 const& data, road_time_t t, road_timerange_t tr)
260{
261 if (sender && sender->hasConnection()) {
262 sender->send(data, t, tr);
263 return true;
264 }
265 return false;
266}
267
268} // namespace pacpus
269
270#endif // IN_OUT_INTERFACE_H
Note: See TracBrowser for help on using the repository browser.