/** * SPDX license identifier: MPL-2.0 * * Copyright (C) 2012, BMW AG * * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012 * \author Aleksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2017 * * \copyright * This Source Code Form is subject to the terms of the * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * \file CAmSocketHandler.h * For further information see http://www.genivi.org/. */ #ifndef SOCKETHANDLER_H_ #define SOCKETHANDLER_H_ #include #include #include #include #include #include #include #include #include #include #include "audiomanagertypes.h" #ifdef WITH_TIMERFD #include #include #include #include #include #endif namespace am { #define MAX_NS 1000000000L #define MAX_TIMERHANDLE UINT16_MAX #define MAX_POLLHANDLE UINT16_MAX typedef uint16_t sh_pollHandle_t; //! class TAmShPollFired: public IAmShPollFired { private: TClass* mInstance; void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData); public: TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) { } ; virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) { (*mInstance.*mFunction)(pollfd, handle, userData); } ; }; /** * template for a callback */ template class TAmShPollCheck: public IAmShPollCheck { private: TClass* mInstance; bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); public: TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) { } ; virtual bool Call(const sh_pollHandle_t handle, void* userData) { return ((*mInstance.*mFunction)(handle, userData)); } ; }; /** * template for a callback */ template class TAmShPollDispatch: public IAmShPollDispatch { private: TClass* mInstance; bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); public: TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) { } ; virtual bool Call(const sh_pollHandle_t handle, void* userData) { return ((*mInstance.*mFunction)(handle, userData)); } ; }; /** * template to create the functor for a class */ template class TAmShTimerCallBack: public IAmShTimerCallBack { private: TClass* mInstance; void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData); public: TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) : IAmShTimerCallBack(), mInstance(instance), // mFunction(function) { } ; virtual void Call(sh_timerHandle_t handle, void* userData) { (*mInstance.*mFunction)(handle, userData); } }; /** * template for a callback */ template class TAmShPollPrepare: public IAmShPollPrepare { private: TClass* mInstance; void (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData); public: TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_pollHandle_t handle, void* userData)) : mInstance(instance), // mFunction(function) { } ; virtual void Call(const sh_pollHandle_t handle, void* userData) { (*mInstance.*mFunction)(handle, userData); } ; }; /** * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler * to get called on communication of the filedescriptors.\n * More information can be found here : \ref mainl */ class CAmSocketHandler { struct sh_poll_s //! prepareCB; //preperation callback std::function firedCB; //fired callback std::function checkCB; //check callback std::function dispatchCB; //dispatch callback void* userData; sh_poll_s() : handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0) { } }; struct sh_timer_s //! callback; //timer callback void* userData; sh_timer_s() : handle(0) #ifdef WITH_TIMERFD , fd(0) #endif , countdown(), callback(), userData(0) { } }; typedef std::reverse_iterator rListTimerIter; //! VectorListPollfd_t; //! VectorListPoll_t; //! prepare, std::function fired, std::function check, std::function dispatch, void* userData, sh_pollHandle_t& handle); am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle); am_Error_e removeFDPoll(const sh_pollHandle_t handle); am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events); am_Error_e addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, #ifndef WITH_TIMERFD const bool __attribute__((__unused__)) repeats = false #else const bool repeats = false #endif ); am_Error_e addTimer(const timespec & timeouts, std::function callback, sh_timerHandle_t& handle, void* userData, #ifndef WITH_TIMERFD const bool __attribute__((__unused__)) repeats = false #else const bool repeats = false #endif ); am_Error_e removeTimer(const sh_timerHandle_t handle); am_Error_e restartTimer(const sh_timerHandle_t handle); am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec & timeouts); am_Error_e stopTimer(const sh_timerHandle_t handle); void start_listenting(); void stop_listening(); void exit_mainloop(); private: static CAmSocketHandler* mInstance; int mPipe[2]; int mDispatchDone; //this starts / stops the mainloop bool fdIsValid(const int fd) const; timespec* insertTime(timespec& buffertime); #ifdef WITH_TIMERFD am_Error_e createTimeFD(const itimerspec & timeouts, int & fd); #else void timerUp(); void timerCorrection(); /** * compares countdown values * @param a * @param b * @return true if b greater a */ inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b) { 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)); } /** * Subtracts b from a * @param a * @param b * @return subtracted value */ inline static timespec timespecSub(const timespec& a, const timespec& b) { timespec result; if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec))) { result.tv_sec = result.tv_nsec = 0; } else { result.tv_sec = a.tv_sec - b.tv_sec; if (a.tv_nsec < b.tv_nsec) { result.tv_nsec = a.tv_nsec + MAX_NS - b.tv_nsec; result.tv_sec--; /* Borrow a second. */ } else { result.tv_nsec = a.tv_nsec - b.tv_nsec; } } return (result); } /** * adds timespec values * @param a * @param b * @return the added values */ inline timespec timespecAdd(const timespec& a, const timespec& b) { timespec result; result.tv_sec = a.tv_sec + b.tv_sec; result.tv_nsec = a.tv_nsec + b.tv_nsec; if (result.tv_nsec >= MAX_NS) { result.tv_sec++; result.tv_nsec = result.tv_nsec - MAX_NS; } return (result); } /** * comapares timespec values * @param a * @param b * @return */ inline int timespecCompare(const timespec& a, const timespec& b) { //less if (a.tv_sec < b.tv_sec) return (-1); //greater else if (a.tv_sec > b.tv_sec) return (1); //less else if (a.tv_nsec < b.tv_nsec) return (-1); //greater else if (a.tv_nsec > b.tv_nsec) return (1); //equal return (0); } #endif /** * functor to prepare all fire events * @param a * @return */ inline static void prepare(am::CAmSocketHandler::sh_poll_s& row); /** * functor to return all fired events * @param a * @return */ inline static void fire(sh_poll_s* a); /** * functor to return all fired events * @param a * @return */ inline static bool eventFired(const pollfd& a); /** * functor to help find the items that do not need dispatching * @param a * @return */ inline static bool noDispatching(const sh_poll_s* a); /** * checks if dispatching is already finished * @param a * @return */ inline static bool dispatchingFinished(const sh_poll_s* a); /** * timer fire callback * @param a * @return */ inline static void callTimer(sh_timer_s& a); VectorListPollfd_t mfdPollingArray; //! mSetPollKeys; //!A set of all used ppoll keys VectorListPoll_t mListPoll; //! mSetTimerKeys; //!A set of all used timer keys std::list mListTimer; //! mListActiveTimer; //!