2 * Copyright (C) 2012, BMW AG
4 * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction,
8 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
13 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 * \file CAmSocketHandler.h
16 * For further information see http://www.genivi.org/.
19 #ifndef SOCKETHANDLER_H_
20 #define SOCKETHANDLER_H_
22 #include "audiomanagertypes.h"
23 #include <sys/socket.h>
30 #include <iostream> //todo: remove me
34 #define MAX_NS 1000000000L
36 static volatile sig_atomic_t gDispatchDone = 1; //this global is used to stop the mainloop
38 typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
39 typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
42 * prototype for poll prepared callback
44 class IAmShPollPrepare
47 virtual void Call(const sh_pollHandle_t handle, void* userData)=0;
48 virtual ~IAmShPollPrepare()
55 * prototype for poll fired callback
60 virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)=0;
61 virtual ~ IAmShPollFired()
68 * prototype for poll check callback
73 virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
74 virtual ~ IAmShPollCheck()
81 * prototype for dispatch callback
83 class IAmShPollDispatch
86 virtual bool Call(const sh_pollHandle_t handle, void* userData)=0;
87 virtual ~ IAmShPollDispatch()
94 * prototype for the timer callback
96 class IAmShTimerCallBack
99 virtual void Call(const sh_timerHandle_t handle, void* userData)=0;
100 virtual ~IAmShTimerCallBack()
107 * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler
108 * to get called on communication of the filedescriptors.\n
109 * More information can be found here : \ref mainl
111 class CAmSocketHandler
114 template<class TClass> class TAmShPollFired: public IAmShPollFired
118 void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
121 TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
122 mInstance(instance), //
123 mFunction(function) {};
125 virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
127 (*mInstance.*mFunction)(pollfd, handle, userData);
131 template<class TClass> class TAmShPollCheck: public IAmShPollCheck
135 bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
138 TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
139 mInstance(instance), //
140 mFunction(function) {};
142 virtual bool Call(const sh_pollHandle_t handle, void* userData)
144 return ((*mInstance.*mFunction)(handle, userData));
151 am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
152 am_Error_e removeFDPoll(const sh_pollHandle_t handle);
153 am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
154 am_Error_e addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void* userData);
155 am_Error_e removeTimer(const sh_timerHandle_t handle);
156 am_Error_e restartTimer(const sh_timerHandle_t handle);
157 am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec timeouts);
158 am_Error_e stopTimer(const sh_timerHandle_t handle);
159 void start_listenting();
160 void stop_listening();
161 void exit_mainloop();
162 void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
168 bool checkerCallback(const sh_pollHandle_t handle, void* userData)
175 TAmShPollFired<CAmSocketHandler> receiverCallbackT;
176 TAmShPollCheck<CAmSocketHandler> checkerCallbackT;
180 static CAmSocketHandler* mInstance;
183 struct sh_timer_s //!<struct that holds information of timers
185 sh_timerHandle_t handle; //!<the handle of the timer
186 timespec countdown; //!<the countdown, this value is decreased every time the timer is up
187 IAmShTimerCallBack* callback; //!<the callbackfunction
188 void * userData; //!<saves a void pointer together with the rest.
191 typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
193 struct sh_poll_s //!<struct that holds information about polls
195 sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
196 IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
197 IAmShPollFired *firedCB; //!<pointer to fired callback
198 IAmShPollCheck *checkCB; //!< pointer to check callback
199 IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
200 pollfd pollfdValue; //!<the array for polling the filedescriptors
201 void *userData; //!<userdata saved together with the callback.
204 typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
205 typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
207 bool fdIsValid(const int fd) const;
209 void timerCorrection();
210 timespec* insertTime(timespec& buffertime);
213 * compares countdown values
216 * @return true if b greater a
218 inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b)
220 return ((a.countdown.tv_sec == b.countdown.tv_sec) ? (a.countdown.tv_nsec < b.countdown.tv_nsec) : (a.countdown.tv_sec < b.countdown.tv_sec));
227 * @return subtracted value
229 inline static timespec timespecSub(const timespec& a, const timespec& b)
233 if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec)))
235 result.tv_sec = result.tv_nsec = 0;
239 result.tv_sec = a.tv_sec - b.tv_sec;
240 if (a.tv_nsec < b.tv_nsec)
242 result.tv_nsec = a.tv_nsec + MAX_NS - b.tv_nsec;
243 result.tv_sec--; /* Borrow a second. */
247 result.tv_nsec = a.tv_nsec - b.tv_nsec;
254 * adds timespec values
257 * @return the added values
259 inline timespec timespecAdd(const timespec& a, const timespec& b)
262 result.tv_sec = a.tv_sec + b.tv_sec;
263 result.tv_nsec = a.tv_nsec + b.tv_nsec;
264 if (result.tv_nsec >= MAX_NS)
267 result.tv_nsec = result.tv_nsec - MAX_NS;
273 * comapares timespec values
278 inline int timespecCompare(const timespec& a, const timespec& b)
281 if (a.tv_sec < b.tv_sec)
284 else if (a.tv_sec > b.tv_sec)
287 else if (a.tv_nsec < b.tv_nsec)
290 else if (a.tv_nsec > b.tv_nsec)
298 * functor to return all fired events
302 inline static bool eventFired(const pollfd& a)
304 return (a.revents == 0 ? false : true);
308 * functor to help find the items that do not need dispatching
312 inline static bool noDispatching(const sh_poll_s& a)
314 //remove from list of there is no checkCB
317 return (!a.checkCB->Call(a.handle, a.userData));
321 * checks if dispatching is already finished
325 inline static bool dispatchingFinished(const sh_poll_s& a)
327 //remove from list of there is no dispatchCB
330 return (!a.dispatchCB->Call(a.handle, a.userData));
333 class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
336 mListPollfd_t& mArray;
338 CAmShCopyPollfd(mListPollfd_t& dest) :
342 void operator()(const sh_poll_s& row)
344 pollfd temp = row.pollfdValue;
346 mArray.push_back(temp);
350 class CAmShCallFire //!< functor to call the firecallbacks
357 void operator()(sh_poll_s& row)
359 row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
363 class CAmShCallPrep //!< functor to call the preparation callbacks
370 void operator()(sh_poll_s& row)
373 row.prepareCB->Call(row.handle, row.userData);
377 class CAmShCallTimer //!<functor to call a timer
384 void operator()(sh_timer_s& row)
386 row.callback->Call(row.handle, row.userData);
390 class CAmShCountdownUp //!<functor that checks if a timer is up
395 CAmShCountdownUp(const timespec& differenceTime) :
396 mDiffTime(differenceTime)
400 bool operator()(const sh_timer_s& row)
402 timespec sub = timespecSub(row.countdown, mDiffTime);
403 if (sub.tv_nsec == 0 && sub.tv_sec == 0)
409 class CAmShCountdownZero //!<functor that checks if a timer is zero
416 bool operator()(const sh_timer_s& row)
418 if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
424 class CAmShSubstractTime //!<functor to easy substract from each countdown value
429 CAmShSubstractTime(timespec param) :
433 inline void operator()(sh_timer_s& t)
435 t.countdown = timespecSub(t.countdown, param);
439 mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
440 mListPoll_t mListPoll; //!<list that holds all information for the ppoll
441 std::list<sh_timer_s> mListTimer; //!<list of all timers
442 std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
443 sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
444 sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
445 bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
446 timespec mStartTime; //!<here the actual time is saved for timecorrection
448 // void debugPrintTimerList ()
450 // std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
451 // for(;it!=mListActiveTimer.end();++it)
453 // std::cout<< "Handle " << it->handle << "sec " << it->countdown.tv_sec << "nsec " << it->countdown.tv_nsec<<std::endl;
460 * template to create the functor for a class
462 template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
466 void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
469 TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
470 mInstance(instance), //
476 virtual void Call(sh_timerHandle_t handle, void* userData)
478 (*mInstance.*mFunction)(handle, userData);
483 * template for a callback
485 template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
489 void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
492 TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
493 mInstance(instance), //
499 virtual void Call(const sh_timerHandle_t handle, void* userData)
501 (*mInstance.*mFunction)(handle, userData);
506 /**make private, not public
507 * template for a callback
509 template<class TClass> class TAmShPollFired: public IAmShPollFired
513 void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
516 TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
517 mInstance(instance), //
523 virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
525 (*mInstance.*mFunction)(pollfd, handle, userData);
531 * template for a callback
533 template<class TClass> class TAmShPollCheck: public IAmShPollCheck
537 bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
540 TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
541 mInstance(instance), //
547 virtual bool Call(const sh_pollHandle_t handle, void* userData)
549 return ((*mInstance.*mFunction)(handle, userData));
555 * template for a callback
557 template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
561 bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
564 TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
565 mInstance(instance), //
571 virtual bool Call(const sh_pollHandle_t handle, void* userData)
573 return ((*mInstance.*mFunction)(handle, userData));
578 #endif /* SOCKETHANDLER_H_ */