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
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
[273]7#include <boost/function.hpp>
[153]8#include <QByteArray>
[200]9#include <QCoreApplication>
[110]10#include <typeinfo>
[89]11
12namespace pacpus {
13
[152]14template <typename T, class C>
[148]15class InputInterface
16 : public InputInterfaceBase
[89]17{
18public:
[199]19 typedef T data_type;
20 typedef C component_type;
[269]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&);
[273]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;
[199]29
[269]30 InputInterface(QString name, C* component, process_data_function_type_with_event processingMethod)
[152]31 : InputInterfaceBase(name, component, component)
[206]32 {
[269]33 mProcessingMethod.fe = processingMethod;
[206]34 }
[269]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 }
[89]53
[148]54 ~InputInterface()
[206]55 {
56 }
[89]57
[199]58 std::size_t getDataSize() const
[148]59 {
60 return sizeof(T);
61 }
[89]62
[269]63 std::type_info const& getDataType() const
[148]64 {
[199]65 return typeid(T);
[148]66 }
[96]67
[199]68 // FIXME: what's the purpose of this function?
[206]69 //PacpusEvent * getEventTemplate()
70 //{
71 // return new PacpusTypedEvent<T>(TYPED_EVENT);
72 //}
[148]73
[199]74 // FIXME: what's the purpose of this function?
[269]75 void customEvent(QEvent* event)
[148]76 {
[269]77 static road_timerange_t const kMaximumBoundedTimeRange = 500;
78
79 if (!event) {
80 LOG_WARN("null event");
81 return;
82 }
83
[206]84 // check that component has been started
85 if ((NULL == getComponent()) || (!getComponent()->isActive())) {
86 LOG_DEBUG("component is not active");
87 return;
88 }
89
[258]90 LOG_TRACE("Receiver: " << getSignature());
[206]91
[269]92 //PacpusTypedEvent<T>* typedEvent = dynamic_cast<PacpusTypedEvent<T> *>(event);
93 PacpusEvent* pacpusEvent = dynamic_cast<PacpusEvent*>(event);
[206]94 if (!pacpusEvent) {
95 LOG_WARN("dynamic_cast failed: not a PacpusEvent");
96 return;
97 }
[269]98 PacpusTypedEvent<T>* typedEvent = dynamic_cast<PacpusTypedEvent<T>*>(pacpusEvent);
[206]99 if (!typedEvent) {
100 LOG_WARN("dynamic_cast failed: incompatible event types");
101 return;
102 }
103
[89]104 switch (event->type()) {
[148]105 case TYPED_EVENT:
[269]106 if (TimeBounded == readingMode() && typedEvent->timerange() < kMaximumBoundedTimeRange) {
107 LOG_WARN("Incorrect TimeRange (< " << kMaximumBoundedTimeRange << "), switching to NeverSkip mode");
[153]108 readingMode() = NeverSkip;
109 }
[110]110
[148]111 switch (readingMode()) {
[110]112 case TimeBounded:
[148]113 if (road_time() - typedEvent->time() > typedEvent->timerange()) {
[206]114 LOG_TRACE("Data skipped, receiver: " << this->getSignature());
[148]115 break;
116 }
[110]117
[269]118 mProcessingMethod.invoke(component(), typedEvent->data(), *typedEvent);
[89]119 break;
[110]120
121 case GetLast:
[269]122 mProcessingMethod.invoke(component(), typedEvent->data(), *typedEvent);
123
[153]124 // delete all remaining events
125 QCoreApplication::removePostedEvents(this, TYPED_EVENT);
[110]126 break;
127
128 case NeverSkip:
[269]129 mProcessingMethod.invoke(component(), typedEvent->data(), *typedEvent);
[159]130 break;
[110]131
132 default:
[159]133 LOG_WARN("Unknown reading mode " << readingMode());
[206]134 break;
[89]135 }
[110]136 break;
[89]137
[184]138 // Add here new event type if needed
[89]139
[110]140 default:
[153]141 LOG_WARN("Unknown event ID " << event->type());
[110]142 break;
[89]143 }
[206]144 event->accept();
[110]145 }
[89]146
[269]147 // TODO: pull mode (NOT YET IMPLEMENTED!!!)
148 T& getData()
[206]149 {
[110]150 T data;
[269]151 // TODO: ask the output data;
[110]152 return data;
[89]153 }
154
155protected:
[269]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 }
[273]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 //}
[269]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;
[89]204};
205
[152]206template <typename T, class C>
[185]207class OutputInterface
208 : public OutputInterfaceBase
[89]209{
210public:
[199]211 typedef T data_type;
212 typedef C component_type;
213
[269]214 OutputInterface(QString name, C* component)
[185]215 : OutputInterfaceBase(name, component, component)
[184]216 {}
[89]217
[199]218 ~OutputInterface()
219 {}
220
[206]221 /// Send data through a typed output
[269]222 void send(T const& data, road_time_t t = road_time(), road_timerange_t tr = 0);
[184]223
[199]224 std::size_t getDataSize() const
[148]225 {
226 return sizeof(T);
227 }
228
[269]229 std::type_info const& getDataType() const
[148]230 {
[199]231 return typeid(T);
[148]232 }
[89]233};
234
[185]235template <typename T, class C>
[269]236void OutputInterface<T, C>::send(T const& data, road_time_t t, road_timerange_t tr)
[185]237{
[269]238 // FIXME: use shared data
[185]239 //QSharedPointer<T> sharedPointer = new T(data);
240
[200]241 for (QList<ConnectionBase>::iterator it = connections().begin(), itend = connections().end(); it != itend; ++it) {
[269]242 // Qt documentation:
[202]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.
[269]245 QEvent* pacpusEvent = new PacpusTypedEvent<T>(TYPED_EVENT, data, t, tr);
[206]246 QCoreApplication::postEvent(
247 it->getInterface(),
[269]248 pacpusEvent,
[206]249 it->getPriority()
250 );
[258]251 LOG_TRACE("Sender: " << it->getInterface()->getSignature());
[185]252 }
253}
254
[202]255template <typename T1, typename T2, class C>
[269]256bool checkedSend(OutputInterface<T1, C>* sender, T2 const& data, road_time_t t = road_time(), road_timerange_t tr = 0);
[202]257
258template <typename T1, typename T2, class C>
[269]259bool checkedSend(OutputInterface<T1, C>* sender, T2 const& data, road_time_t t, road_timerange_t tr)
[202]260{
261 if (sender && sender->hasConnection()) {
262 sender->send(data, t, tr);
263 return true;
264 }
265 return false;
266}
267
[89]268} // namespace pacpus
269
270#endif // IN_OUT_INTERFACE_H
Note: See TracBrowser for help on using the repository browser.