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 static void static_exit_mainloop();
163 void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
169 bool checkerCallback(const sh_pollHandle_t handle, void* userData)
176 TAmShPollFired<CAmSocketHandler> receiverCallbackT;
177 TAmShPollCheck<CAmSocketHandler> checkerCallbackT;
181 static CAmSocketHandler* mInstance;
184 struct sh_timer_s //!<struct that holds information of timers
186 sh_timerHandle_t handle; //!<the handle of the timer
187 timespec countdown; //!<the countdown, this value is decreased every time the timer is up
188 IAmShTimerCallBack* callback; //!<the callbackfunction
189 void * userData; //!<saves a void pointer together with the rest.
192 typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
194 struct sh_poll_s //!<struct that holds information about polls
196 sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
197 IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
198 IAmShPollFired *firedCB; //!<pointer to fired callback
199 IAmShPollCheck *checkCB; //!< pointer to check callback
200 IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
201 pollfd pollfdValue; //!<the array for polling the filedescriptors
202 void *userData; //!<userdata saved together with the callback.
205 typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
206 typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
208 bool fdIsValid(const int fd) const;
210 void timerCorrection();
211 timespec* insertTime(timespec& buffertime);
214 * compares countdown values
217 * @return true if b greater a
219 inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b)
221 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));
228 * @return subtracted value
230 inline static timespec timespecSub(const timespec& a, const timespec& b)
234 if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec)))
236 result.tv_sec = result.tv_nsec = 0;
240 result.tv_sec = a.tv_sec - b.tv_sec;
241 if (a.tv_nsec < b.tv_nsec)
243 result.tv_nsec = a.tv_nsec + MAX_NS - b.tv_nsec;
244 result.tv_sec--; /* Borrow a second. */
248 result.tv_nsec = a.tv_nsec - b.tv_nsec;
255 * adds timespec values
258 * @return the added values
260 inline timespec timespecAdd(const timespec& a, const timespec& b)
263 result.tv_sec = a.tv_sec + b.tv_sec;
264 result.tv_nsec = a.tv_nsec + b.tv_nsec;
265 if (result.tv_nsec >= MAX_NS)
268 result.tv_nsec = result.tv_nsec - MAX_NS;
274 * comapares timespec values
279 inline int timespecCompare(const timespec& a, const timespec& b)
282 if (a.tv_sec < b.tv_sec)
285 else if (a.tv_sec > b.tv_sec)
288 else if (a.tv_nsec < b.tv_nsec)
291 else if (a.tv_nsec > b.tv_nsec)
299 * functor to return all fired events
303 inline static bool eventFired(const pollfd& a)
305 return (a.revents == 0 ? false : true);
309 * functor to help find the items that do not need dispatching
313 inline static bool noDispatching(const sh_poll_s& a)
315 //remove from list of there is no checkCB
318 return (!a.checkCB->Call(a.handle, a.userData));
322 * checks if dispatching is already finished
326 inline static bool dispatchingFinished(const sh_poll_s& a)
328 //remove from list of there is no dispatchCB
331 return (!a.dispatchCB->Call(a.handle, a.userData));
334 class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
337 mListPollfd_t& mArray;
339 CAmShCopyPollfd(mListPollfd_t& dest) :
343 void operator()(const sh_poll_s& row)
345 pollfd temp = row.pollfdValue;
347 mArray.push_back(temp);
351 class CAmShCallFire //!< functor to call the firecallbacks
358 void operator()(sh_poll_s& row)
360 row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
364 class CAmShCallPrep //!< functor to call the preparation callbacks
371 void operator()(sh_poll_s& row)
374 row.prepareCB->Call(row.handle, row.userData);
378 class CAmShCallTimer //!<functor to call a timer
385 void operator()(sh_timer_s& row)
387 row.callback->Call(row.handle, row.userData);
391 class CAmShCountdownUp //!<functor that checks if a timer is up
396 CAmShCountdownUp(const timespec& differenceTime) :
397 mDiffTime(differenceTime)
401 bool operator()(const sh_timer_s& row)
403 timespec sub = timespecSub(row.countdown, mDiffTime);
404 if (sub.tv_nsec == 0 && sub.tv_sec == 0)
410 class CAmShCountdownZero //!<functor that checks if a timer is zero
417 bool operator()(const sh_timer_s& row)
419 if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
425 class CAmShSubstractTime //!<functor to easy substract from each countdown value
430 CAmShSubstractTime(timespec param) :
434 inline void operator()(sh_timer_s& t)
436 t.countdown = timespecSub(t.countdown, param);
440 mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
441 mListPoll_t mListPoll; //!<list that holds all information for the ppoll
442 std::list<sh_timer_s> mListTimer; //!<list of all timers
443 std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
444 sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
445 sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
446 bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
447 timespec mStartTime; //!<here the actual time is saved for timecorrection
449 // void debugPrintTimerList ()
451 // std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
452 // for(;it!=mListActiveTimer.end();++it)
454 // std::cout<< "Handle " << it->handle << "sec " << it->countdown.tv_sec << "nsec " << it->countdown.tv_nsec<<std::endl;
461 * template to create the functor for a class
463 template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
467 void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
470 TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
471 mInstance(instance), //
477 virtual void Call(sh_timerHandle_t handle, void* userData)
479 (*mInstance.*mFunction)(handle, userData);
484 * template for a callback
486 template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
490 void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
493 TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
494 mInstance(instance), //
500 virtual void Call(const sh_timerHandle_t handle, void* userData)
502 (*mInstance.*mFunction)(handle, userData);
507 /**make private, not public
508 * template for a callback
510 template<class TClass> class TAmShPollFired: public IAmShPollFired
514 void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
517 TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
518 mInstance(instance), //
524 virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
526 (*mInstance.*mFunction)(pollfd, handle, userData);
532 * template for a callback
534 template<class TClass> class TAmShPollCheck: public IAmShPollCheck
538 bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
541 TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
542 mInstance(instance), //
548 virtual bool Call(const sh_pollHandle_t handle, void* userData)
550 return ((*mInstance.*mFunction)(handle, userData));
556 * template for a callback
558 template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
562 bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
565 TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
566 mInstance(instance), //
572 virtual bool Call(const sh_pollHandle_t handle, void* userData)
574 return ((*mInstance.*mFunction)(handle, userData));
579 #endif /* SOCKETHANDLER_H_ */