summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandar Donchev <Aleksander.Donchev@partner.bmw.de>2017-02-21 15:11:15 +0100
committerChristian Linke <christian.linke@bmw.de>2017-05-02 06:25:51 -0700
commit551d34d6f69e7def9590f503f23dad220011f118 (patch)
treef243261bc2fbb679c9d51a51b792e4e4739d098e
parent8f2387e42641c7c2b967553a4c578f0e87549fb6 (diff)
downloadaudiomanager-551d34d6f69e7def9590f503f23dad220011f118.tar.gz
Linux specific TIMERFD implementation as alternative timer mechanism
Signed-off-by: Christian Linke <christian.linke@bmw.de>
-rw-r--r--AudioManagerUtilities/include/CAmSocketHandler.h814
-rw-r--r--AudioManagerUtilities/src/CAmSocketHandler.cpp1172
-rwxr-xr-xCMakeLists.txt6
-rw-r--r--cmake/AudioManagerUtilitiesConfig.cmake.in1
-rw-r--r--cmake/config.cmake.in1
5 files changed, 1133 insertions, 861 deletions
diff --git a/AudioManagerUtilities/include/CAmSocketHandler.h b/AudioManagerUtilities/include/CAmSocketHandler.h
index 5c3c5ba..7ccfd16 100644
--- a/AudioManagerUtilities/include/CAmSocketHandler.h
+++ b/AudioManagerUtilities/include/CAmSocketHandler.h
@@ -4,6 +4,7 @@
* 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
@@ -17,7 +18,6 @@
#ifndef SOCKETHANDLER_H_
#define SOCKETHANDLER_H_
-#include "audiomanagertypes.h"
#include <sys/socket.h>
#include <stdint.h>
#include <sys/poll.h>
@@ -25,6 +25,19 @@
#include <map>
#include <set>
#include <signal.h>
+#include <vector>
+#include <audiomanagerconfig.h>
+#include "audiomanagertypes.h"
+
+#ifdef WITH_TIMERFD
+
+#include <stdio.h>
+#include <string>
+#include <stdexcept>
+#include <unistd.h>
+#include <fcntl.h>
+
+#endif
namespace am
{
@@ -33,67 +46,79 @@ namespace am
#define MAX_TIMERHANDLE INT16_MAX
#define MAX_POLLHANDLE INT16_MAX
-typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
-typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
+ typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
+ typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
-/**
- * prototype for poll prepared callback
- */
-class IAmShPollPrepare
-{
-public:
- virtual void Call(const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~IAmShPollPrepare() {};
-};
+ /**
+ * prototype for poll prepared callback
+ */
+ class IAmShPollPrepare
+ {
+ public:
+ virtual void Call(const sh_pollHandle_t handle, void* userData) = 0;
+ virtual ~IAmShPollPrepare()
+ {
+ }
+ ;
+ };
-/**
- * prototype for poll fired callback
- */
-class IAmShPollFired
-{
-public:
- virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~ IAmShPollFired() {};
-};
+ /**
+ * prototype for poll fired callback
+ */
+ class IAmShPollFired
+ {
+ public:
+ virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) = 0;
+ virtual ~ IAmShPollFired()
+ {
+ }
+ ;
+ };
-/**
- * prototype for poll check callback
- */
-class IAmShPollCheck
-{
-public:
- virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~ IAmShPollCheck() {};
-};
+ /**
+ * prototype for poll check callback
+ */
+ class IAmShPollCheck
+ {
+ public:
+ virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0;
+ virtual ~ IAmShPollCheck()
+ {
+ }
+ ;
+ };
-/**
- * prototype for dispatch callback
- */
-class IAmShPollDispatch
-{
-public:
- virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~ IAmShPollDispatch() {};
-};
+ /**
+ * prototype for dispatch callback
+ */
+ class IAmShPollDispatch
+ {
+ public:
+ virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0;
+ virtual ~ IAmShPollDispatch()
+ {
+ }
+ ;
+ };
-/**
- * prototype for the timer callback
- */
-class IAmShTimerCallBack
-{
-public:
- virtual void Call(const sh_timerHandle_t handle, void* userData) = 0;
- virtual ~IAmShTimerCallBack() {};
-};
+ /**
+ * prototype for the timer callback
+ */
+ class IAmShTimerCallBack
+ {
+ public:
+ IAmShTimerCallBack()
+ {
+ }
+ virtual void Call(const sh_timerHandle_t handle, void* userData) = 0;
+ virtual ~IAmShTimerCallBack()
+ {
+ }
+ };
-/**
- * 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
-{
-public:
+ /**make private, not public
+ * template for a callback
+ */
template<class TClass> class TAmShPollFired: public IAmShPollFired
{
private:
@@ -103,14 +128,21 @@ public:
public:
TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
mInstance(instance), //
- mFunction(function) {};
+ 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 TClass> class TAmShPollCheck: public IAmShPollCheck
{
private:
@@ -120,367 +152,423 @@ public:
public:
TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
mInstance(instance), //
- mFunction(function) {};
+ mFunction(function)
+ {
+ }
+ ;
virtual bool Call(const sh_pollHandle_t handle, void* userData)
{
return ((*mInstance.*mFunction)(handle, userData));
- };
+ }
+ ;
};
- CAmSocketHandler();
- ~CAmSocketHandler();
-
- 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);
- 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();
- void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
- {
- (void) pollfd;
- (void) handle;
- (void) userData;
- };
- bool checkerCallback(const sh_pollHandle_t handle, void* userData)
- {
- (void) handle;
- (void) userData;
- return (false);
- };
-
- TAmShPollFired<CAmSocketHandler> receiverCallbackT;
- TAmShPollCheck<CAmSocketHandler> checkerCallbackT;
-
-private:
-
- static CAmSocketHandler* mInstance;
- int mPipe[2];
- int mDispatchDone; //this starts / stops the mainloop
- struct sh_timer_s //!<struct that holds information of timers
+ /**
+ * template for a callback
+ */
+ template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
{
- sh_timerHandle_t handle; //!<the handle of the timer
- timespec countdown; //!<the countdown, this value is decreased every time the timer is up
- IAmShTimerCallBack* callback; //!<the callbackfunction
- void * userData; //!<saves a void pointer together with the rest.
- };
+ private:
+ TClass* mInstance;
+ bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
- typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
+ public:
+ TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
+ mInstance(instance), //
+ mFunction(function)
+ {
+ }
+ ;
- struct sh_poll_s //!<struct that holds information about polls
- {
- sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
- IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
- IAmShPollFired *firedCB; //!<pointer to fired callback
- IAmShPollCheck *checkCB; //!< pointer to check callback
- IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
- pollfd pollfdValue; //!<the array for polling the filedescriptors
- void *userData; //!<userdata saved together with the callback.
+ virtual bool Call(const sh_pollHandle_t handle, void* userData)
+ {
+ return ((*mInstance.*mFunction)(handle, userData));
+ }
+ ;
};
- typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
- typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
-
- bool fdIsValid(const int fd) const;
- void timerUp();
- void timerCorrection();
- timespec* insertTime(timespec& buffertime);
-
- /**
- * 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
+ * template to create the functor for a class
*/
- inline static timespec timespecSub(const timespec& a, const timespec& b)
+ template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
{
- timespec result;
+ private:
+ TClass* mInstance;
+ void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
- if ((a.tv_sec < b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_nsec <= b.tv_nsec)))
+ public:
+ TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
+ IAmShTimerCallBack(), mInstance(instance), //
+ mFunction(function)
{
- result.tv_sec = result.tv_nsec = 0;
}
- else
+ ;
+
+ virtual void Call(sh_timerHandle_t handle, void* userData)
{
- 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;
- }
+ (*mInstance.*mFunction)(handle, userData);
}
- return (result);
- }
+ };
/**
- * adds timespec values
- * @param a
- * @param b
- * @return the added values
+ * template for a callback
*/
- inline timespec timespecAdd(const timespec& a, const timespec& b)
+ template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
{
- 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)
+ private:
+ TClass* mInstance;
+ void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
+
+ public:
+ TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
+ mInstance(instance), //
+ mFunction(function)
{
- 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);
- }
+ virtual void Call(const sh_timerHandle_t handle, void* userData)
+ {
+ (*mInstance.*mFunction)(handle, userData);
+ }
+ ;
+ };
/**
- * functor to return all fired events
- * @param a
- * @return
+ * 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
*/
- inline static bool eventFired(const pollfd& a)
+ class CAmSocketHandler
{
- return (a.revents == 0 ? false : true);
- }
+ struct sh_poll_s //!<struct that holds information about polls
+ {
+ sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
+ IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
+ IAmShPollFired *firedCB; //!<pointer to fired callback
+ IAmShPollCheck *checkCB; //!< pointer to check callback
+ IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
+ pollfd pollfdValue; //!<the array for polling the filedescriptors
+ void *userData; //!<userdata saved together with the callback.
+ };
- /**
- * functor to help find the items that do not need dispatching
- * @param a
- * @return
- */
- inline static bool noDispatching(const sh_poll_s& a)
- {
- //remove from list of there is no checkCB
- if (!a.checkCB)
- return (true);
- return (!a.checkCB->Call(a.handle, a.userData));
- }
+ struct sh_timer_s //!<struct that holds information of timers
+ {
+ sh_timerHandle_t handle; //!<the handle of the timer
+#ifdef WITH_TIMERFD
+ int fd;
+ itimerspec countdown; //!<the countdown, this value is decreased every time the timer is up
+#else
+ timespec countdown; //!<the countdown, this value is decreased every time the timer is up
+#endif
+ IAmShTimerCallBack* callback; //!<the callbackfunction
+ void * userData; //!<saves a void pointer together with the rest.
+ };
- /**
- * checks if dispatching is already finished
- * @param a
- * @return
- */
- inline static bool dispatchingFinished(const sh_poll_s& a)
- {
- //remove from list of there is no dispatchCB
- if (!a.dispatchCB)
- return (true);
- return (!a.dispatchCB->Call(a.handle, a.userData));
- }
+ typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
- class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
- {
- private:
- mListPollfd_t& mArray;
- public:
- CAmShCopyPollfd(mListPollfd_t& dest) : mArray(dest) {}
- void operator()(const sh_poll_s& row);
- };
+ typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
+ typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
- class CAmShCallFire //!< functor to call the firecallbacks
- {
- public:
- CAmShCallFire() {};
- void operator()(sh_poll_s& row);
- };
+#ifdef WITH_TIMERFD
+ /**
+ * Wrapper for IAmShTimerCallBack.
+ * Timerfds are normal file descriptors and therefore they should be added to the handler through the method addFDPoll.
+ */
+ class TAmShPollTimerFired: public IAmShPollFired, public IAmShPollCheck
+ {
+ IAmShTimerCallBack* mCallback;
+ uint64_t mExpirations;
+ public:
+ TAmShPollTimerFired(IAmShTimerCallBack * cb) :
+ mCallback(cb), mExpirations(0)
+ {
+ }
- class CAmShCallPrep //!< functor to call the preparation callbacks
- {
- public:
- CAmShCallPrep() {};
- void operator()(sh_poll_s& row);
- };
+ void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
+ {
+ if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1)
+ {
+ //error received...try again
+ read(pollfd.fd, &mExpirations, sizeof(uint64_t));
+ }
+ }
- class CAmShCallTimer //!<functor to call a timer
- {
+ bool Call(const sh_pollHandle_t handle, void* userData)
+ {
+ mCallback->Call(handle, userData);
+ return false;
+ }
+ };
+#endif
public:
- CAmShCallTimer() {};
- void operator()(sh_timer_s& row);
- };
- class CAmShCountdownUp //!<functor that checks if a timer is up
- {
- private:
- timespec mDiffTime;
- public:
- CAmShCountdownUp(const timespec& differenceTime) : mDiffTime(differenceTime) {};
- bool operator()(const sh_timer_s& row);
- };
+ CAmSocketHandler();
+ ~CAmSocketHandler();
+
+ 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 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();
+ void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
+ {
+ (void) pollfd;
+ (void) handle;
+ (void) userData;
+ }
- class CAmShCountdownZero //!<functor that checks if a timer is zero
- {
- public:
- CAmShCountdownZero() {};
- bool operator()(const sh_timer_s& row);
- };
+ bool checkerCallback(const sh_pollHandle_t handle, void* userData)
+ {
+ (void) handle;
+ (void) userData;
+ return (false);
+ }
- class CAmShSubstractTime //!<functor to easy substract from each countdown value
- {
private:
- timespec param;
- public:
- CAmShSubstractTime(timespec param) : param(param) {}
- inline void operator()(sh_timer_s& t)
+ TAmShPollFired<CAmSocketHandler> mReceiverCallbackT;
+ TAmShPollCheck<CAmSocketHandler> mCheckerCallbackT;
+#ifdef WITH_TIMERFD
+ std::list<TAmShPollTimerFired> mTimerCallbackT;
+#endif
+
+ 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)
{
- t.countdown = timespecSub(t.countdown, param);
+ 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));
}
- };
- mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
- std::set<sh_pollHandle_t> mSetPollKeys; //!A set of all used ppoll keys
- mListPoll_t mListPoll; //!<list that holds all information for the ppoll
- std::set<sh_timerHandle_t> mSetTimerKeys; //!A set of all used timer keys
- std::list<sh_timer_s> mListTimer; //!<list of all timers
- std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
- sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
- sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
- bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
- timespec mStartTime; //!<here the actual time is saved for timecorrection
-
-};
-
-/**
- * template to create the functor for a class
- */
-template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
-{
-private:
- TClass* mInstance;
- void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
+ /**
+ * Subtracts b from a
+ * @param a
+ * @param b
+ * @return subtracted value
+ */
+ inline static timespec timespecSub(const timespec& a, const timespec& b)
+ {
+ timespec result;
-public:
- TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+ 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);
+ }
- virtual void Call(sh_timerHandle_t handle, void* userData)
- {
- (*mInstance.*mFunction)(handle, userData);
- }
-};
+ /**
+ * 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);
+ }
-/**
- * template for a callback
- */
-template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
-{
-private:
- TClass* mInstance;
- void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
+ /**
+ * 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 return all fired events
+ * @param a
+ * @return
+ */
+ inline static bool eventFired(const pollfd& a)
+ {
+ return (a.revents == 0 ? false : true);
+ }
-public:
- TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+ /**
+ * functor to help find the items that do not need dispatching
+ * @param a
+ * @return
+ */
+ inline static bool noDispatching(const sh_poll_s& a)
+ {
+ //remove from list of there is no checkCB
+ if (!a.checkCB)
+ return (true);
+ return (!a.checkCB->Call(a.handle, a.userData));
+ }
- virtual void Call(const sh_timerHandle_t handle, void* userData)
- {
- (*mInstance.*mFunction)(handle, userData);
- };
-};
+ /**
+ * checks if dispatching is already finished
+ * @param a
+ * @return
+ */
+ inline static bool dispatchingFinished(const sh_poll_s& a)
+ {
+ //remove from list of there is no dispatchCB
+ if (!a.dispatchCB)
+ return (true);
+ return (!a.dispatchCB->Call(a.handle, a.userData));
+ }
-/**make private, not public
- * template for a callback
- */
-template<class TClass> class TAmShPollFired: public IAmShPollFired
-{
-private:
- TClass* mInstance;
- void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
+ class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
+ {
+ private:
+ mListPollfd_t& mArray;
+ public:
+ CAmShCopyPollfd(mListPollfd_t& dest) :
+ mArray(dest)
+ {
+ }
+ void operator()(const sh_poll_s& row);
+ };
-public:
- TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+ class CAmShCallFire //!< functor to call the firecallbacks
+ {
+ public:
+ CAmShCallFire()
+ {
+ }
+ ;
+ void operator()(sh_poll_s& row);
+ };
- virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
- {
- (*mInstance.*mFunction)(pollfd, handle, userData);
- };
-};
+ class CAmShCallPrep //!< functor to call the preparation callbacks
+ {
+ public:
+ CAmShCallPrep()
+ {
+ }
+ ;
+ void operator()(sh_poll_s& row);
+ };
-/**
- * template for a callback
- */
-template<class TClass> class TAmShPollCheck: public IAmShPollCheck
-{
-private:
- TClass* mInstance;
- bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
+ class CAmShCallTimer //!<functor to call a timer
+ {
+ public:
+ CAmShCallTimer()
+ {
+ }
+ ;
+ void operator()(sh_timer_s& row);
+ };
-public:
- TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+ class CAmShCountdownUp //!<functor that checks if a timer is up
+ {
+ private:
+ timespec mDiffTime;
+ public:
+ CAmShCountdownUp(const timespec& differenceTime) :
+ mDiffTime(differenceTime)
+ {
+ }
+ ;
+ bool operator()(const sh_timer_s& row);
+ };
+#ifndef WITH_TIMERFD
+ class CAmShCountdownZero //!<functor that checks if a timer is zero
+ {
+ public:
+ CAmShCountdownZero()
+ {};
+ bool operator()(const sh_timer_s& row);
+ };
- virtual bool Call(const sh_pollHandle_t handle, void* userData)
- {
- return ((*mInstance.*mFunction)(handle, userData));
+ class CAmShSubstractTime //!<functor to easy substract from each countdown value
+ {
+ private:
+ timespec param;
+ public:
+ CAmShSubstractTime(timespec param) : param(param)
+ {}
+ inline void operator()(sh_timer_s& t)
+ {
+ t.countdown = timespecSub(t.countdown, param);
+ }
+ };
+#endif
+ mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
+ std::set<sh_pollHandle_t> mSetPollKeys; //!A set of all used ppoll keys
+ mListPoll_t mListPoll; //!<list that holds all information for the ppoll
+ std::set<sh_timerHandle_t> mSetTimerKeys; //!A set of all used timer keys
+ std::list<sh_timer_s> mListTimer; //!<list of all timers
+ std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
+ sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
+ sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
+ bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
+#ifndef WITH_TIMERFD
+ timespec mStartTime; //!<here the actual time is saved for timecorrection
+#endif
};
-};
-/**
- * template for a callback
- */
-template<class TClass> 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));
- };
-};
} /* namespace am */
#endif /* SOCKETHANDLER_H_ */
diff --git a/AudioManagerUtilities/src/CAmSocketHandler.cpp b/AudioManagerUtilities/src/CAmSocketHandler.cpp
index 1092198..56df45c 100644
--- a/AudioManagerUtilities/src/CAmSocketHandler.cpp
+++ b/AudioManagerUtilities/src/CAmSocketHandler.cpp
@@ -15,13 +15,13 @@
*
*
* \author Christian Linke, christian.linke@bmw.de BMW 2011,2012
+ * \author Aleksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2017
*
* \file CAmSocketHandler.cpp
* For further information see http://www.genivi.org/.
*
*/
-#include "CAmSocketHandler.h"
#include <cassert>
#include <sys/fcntl.h>
#include <sys/errno.h>
@@ -32,618 +32,796 @@
#include <csignal>
#include <unistd.h>
#include "CAmDltWrapper.h"
+#include "CAmSocketHandler.h"
-namespace am
-{
+#ifdef WITH_TIMERFD
+#include <sys/timerfd.h>
+#endif
-CAmSocketHandler::CAmSocketHandler() :
- receiverCallbackT(this, &CAmSocketHandler::receiverCallback),//
- checkerCallbackT(this, &CAmSocketHandler::checkerCallback),//
- mPipe(), //
- mDispatchDone(1),//
- mListPoll(), //
- mListTimer(), //
- mListActiveTimer(), //
- mLastInsertedHandle(0), //
- mLastInsertedPollHandle(0), //
- mRecreatePollfds(true), //
- mStartTime() //
-{
- if (pipe(mPipe) == -1)
- {
- logError("Sockethandler could not create pipe!");
- }
-
- //add the pipe to the poll - nothing needs to be proccessed here we just need the pipe to trigger the ppoll
- short event = 0;
- sh_pollHandle_t handle;
- event |= POLLIN;
- addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, &checkerCallbackT, NULL, NULL, handle);
-}
-
-CAmSocketHandler::~CAmSocketHandler()
+namespace am
{
- close(mPipe[0]);
- close(mPipe[1]);
-}
-//todo: maybe have some: give me more time returned?
-/**
- * start the block listening for filedescriptors. This is the mainloop.
- */
-void CAmSocketHandler::start_listenting()
-{
- mDispatchDone = 0;
- int16_t pollStatus;
-
- //prepare the signalmask
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGINT);
- sigaddset(&sigmask, SIGQUIT);
- sigaddset(&sigmask, SIGTERM);
- sigaddset(&sigmask, SIGHUP);
- sigaddset(&sigmask, SIGQUIT);
-
- clock_gettime(CLOCK_MONOTONIC, &mStartTime);
- while (!mDispatchDone)
+ CAmSocketHandler::CAmSocketHandler() :
+ mReceiverCallbackT(this, &CAmSocketHandler::receiverCallback), //
+ mCheckerCallbackT(this, &CAmSocketHandler::checkerCallback), //
+#ifdef WITH_TIMERFD
+ mTimerCallbackT(), //
+#endif
+ mPipe(), //
+ mDispatchDone(1), //
+ mListPoll(), //
+ mListTimer(), //
+ mListActiveTimer(), //
+ mLastInsertedHandle(0), //
+ mLastInsertedPollHandle(0), //
+ mRecreatePollfds(true)
+#ifndef WITH_TIMERFD
+ ,mStartTime() //
+#endif
{
- //first we go through the registered filedescriptors and check if someone needs preparation:
- std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCallPrep());
-
- if (mRecreatePollfds)
+ if (pipe(mPipe) == -1)
{
- mfdPollingArray.clear();
- //there was a change in the setup, so we need to recreate the fdarray from the list
- std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCopyPollfd(mfdPollingArray));
- mRecreatePollfds = false;
+ logError("Sockethandler could not create pipe!");
}
- timerCorrection();
-
- //block until something is on a filedescriptor
+ //add the pipe to the poll - nothing needs to be proccessed here we just need the pipe to trigger the ppoll
+ short event = 0;
+ sh_pollHandle_t handle;
+ event |= POLLIN;
+ addFDPoll(mPipe[0], event, NULL, &mReceiverCallbackT, &mCheckerCallbackT, NULL, NULL, handle);
+ }
- timespec buffertime;
- if ((pollStatus = ppoll(&mfdPollingArray[0], mfdPollingArray.size(), insertTime(buffertime), &sigmask)) < 0)
+ CAmSocketHandler::~CAmSocketHandler()
+ {
+#ifdef WITH_TIMERFD
+ for(auto it: mListTimer)
{
- if (errno == EINTR)
- {
- //a signal was received, that means it's time to go...
- pollStatus = 0;
- }
- else
- {
- logError("SocketHandler::start_listenting ppoll returned with error", errno);
- throw std::runtime_error(std::string("SocketHandler::start_listenting ppoll returned with error."));
- }
+ close(it.fd);
}
+#endif
+ close(mPipe[0]);
+ close(mPipe[1]);
+ }
- if (pollStatus != 0) //only check filedescriptors if there was a change
+//todo: maybe have some: give me more time returned?
+ /**
+ * start the block listening for filedescriptors. This is the mainloop.
+ */
+ void CAmSocketHandler::start_listenting()
+ {
+ mDispatchDone = 0;
+ int16_t pollStatus;
+
+ //prepare the signalmask
+ sigset_t sigmask;
+ sigemptyset(&sigmask);
+ sigaddset(&sigmask, SIGINT);
+ sigaddset(&sigmask, SIGQUIT);
+ sigaddset(&sigmask, SIGTERM);
+ sigaddset(&sigmask, SIGHUP);
+ sigaddset(&sigmask, SIGQUIT);
+#ifndef WITH_TIMERFD
+ clock_gettime(CLOCK_MONOTONIC, &mStartTime);
+#endif
+ while (!mDispatchDone)
{
- //todo: here could be a timer that makes sure naughty plugins return!
+ //first we go through the registered filedescriptors and check if someone needs preparation:
+ std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCallPrep());
- //freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
- std::list<sh_poll_s> listPoll;
- mListPoll_t::iterator listmPollIt;
+ if (mRecreatePollfds)
+ {
+ mfdPollingArray.clear();
+ //there was a change in the setup, so we need to recreate the fdarray from the list
+ std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCopyPollfd(mfdPollingArray));
+ mRecreatePollfds = false;
+ }
+#ifndef WITH_TIMERFD
+ timerCorrection();
+#endif
+ //block until something is on a filedescriptor
- //remove all filedescriptors who did not fire
- std::vector<pollfd>::iterator it = mfdPollingArray.begin();
- do
+ timespec buffertime;
+ if ((pollStatus = ppoll(&mfdPollingArray[0], mfdPollingArray.size(), insertTime(buffertime), &sigmask)) < 0)
{
- it = std::find_if(it, mfdPollingArray.end(), eventFired);
- if (it != mfdPollingArray.end())
+ if (errno == EINTR)
{
- listmPollIt = mListPoll.begin();
- std::advance(listmPollIt, std::distance(mfdPollingArray.begin(), it));
- listPoll.push_back(*listmPollIt);
- listPoll.back().pollfdValue = *it;
- it++;
+ //a signal was received, that means it's time to go...
+ pollStatus = 0;
}
- } while (it != mfdPollingArray.end());
+ else
+ {
+ logError("SocketHandler::start_listenting ppoll returned with error", errno);
+ throw std::runtime_error(std::string("SocketHandler::start_listenting ppoll returned with error."));
+ }
+ }
+
+ if (pollStatus != 0) //only check filedescriptors if there was a change
+ {
+ //todo: here could be a timer that makes sure naughty plugins return!
- //stage 1, call firedCB
- std::for_each(listPoll.begin(), listPoll.end(), CAmShCallFire());
+ //freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
+ std::list<sh_poll_s> listPoll;
+ mListPoll_t::iterator listmPollIt;
- //stage 2, lets ask around if some dispatching is necessary, the ones who need stay on the list
- listPoll.remove_if(noDispatching);
+ //remove all filedescriptors who did not fire
+ std::vector<pollfd>::iterator it = mfdPollingArray.begin();
+ do
+ {
+ it = std::find_if(it, mfdPollingArray.end(), eventFired);
+ if (it != mfdPollingArray.end())
+ {
+ listmPollIt = mListPoll.begin();
+ std::advance(listmPollIt, std::distance(mfdPollingArray.begin(), it));
+ listPoll.push_back(*listmPollIt);
+ listPoll.back().pollfdValue = *it;
+ it++;
+ }
+ } while (it != mfdPollingArray.end());
+
+ //stage 1, call firedCB
+ std::for_each(listPoll.begin(), listPoll.end(), CAmShCallFire());
+
+ //stage 2, lets ask around if some dispatching is necessary, the ones who need stay on the list
+ listPoll.erase(std::remove_if(listPoll.begin(), listPoll.end(), noDispatching), listPoll.end());
+
+ //stage 3, the ones left need to dispatch, we do this as long as there is something to dispatch..
+ do
+ {
+ listPoll.erase(std::remove_if(listPoll.begin(), listPoll.end(), dispatchingFinished), listPoll.end());
+ } while (!listPoll.empty());
- //stage 3, the ones left need to dispatch, we do this as long as there is something to dispatch..
- do
+ }
+#ifndef WITH_TIMERFD
+ else //Timerevent
{
- listPoll.remove_if(dispatchingFinished);
- } while (!listPoll.empty());
-
+ //this was a timer event, we need to take care about the timers
+ timerUp();
+ }
+#endif
}
- else //Timerevent
+ }
+
+ /**
+ * exits the loop
+ */
+ void CAmSocketHandler::stop_listening()
+ {
+ mDispatchDone = 1;
+#ifndef WITH_TIMERFD
+ //this is for all running timers only - we need to handle the additional offset here
+ if (!mListActiveTimer.empty())
{
- //this was a timer event, we need to take care about the timers
- timerUp();
+ timespec currentTime, correctionTime;
+ clock_gettime(CLOCK_MONOTONIC, &currentTime);
+ correctionTime = timespecSub(currentTime, mStartTime);
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
}
+#endif
}
-}
-
-/**
- * exits the loop
- */
-void CAmSocketHandler::stop_listening()
-{
- mDispatchDone = 1;
- //this is for all running timers only - we need to handle the additional offset here
- if (!mListActiveTimer.empty())
+ void CAmSocketHandler::exit_mainloop()
{
- timespec currentTime, correctionTime;
- clock_gettime(CLOCK_MONOTONIC, &currentTime);
- correctionTime = timespecSub(currentTime, mStartTime);
- std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
- }
+ //end the while loop
+ stop_listening();
-}
+ //fire the ending filedescriptor
+ int p(1);
+ ssize_t result = write(mPipe[1], &p, sizeof(p));
+ }
-/**
- * Adds a filedescriptor to the polling loop
- * @param fd the filedescriptor
- * @param event the event flags
- * @param prepare a callback that is called before the loop is entered
- * @param fired a callback that is called when the filedescriptor needs to be read
- * @param check a callback that is called to check if further actions are neccessary
- * @param dispatch a callback that is called to dispatch the received data
- * @param userData a pointer to userdata that is always passed around
- * @param handle the handle of this poll
- * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
- */
-am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle)
-{
- if (!fdIsValid(fd))
- return (E_NON_EXISTENT);
-
- //create a new handle for the poll
- sh_pollHandle_t lastHandle(mLastInsertedPollHandle);
- do
+ /**
+ * Adds a filedescriptor to the polling loop
+ * @param fd the filedescriptor
+ * @param event the event flags
+ * @param prepare a callback that is called before the loop is entered
+ * @param fired a callback that is called when the filedescriptor needs to be read
+ * @param check a callback that is called to check if further actions are neccessary
+ * @param dispatch a callback that is called to dispatch the received data
+ * @param userData a pointer to userdata that is always passed around
+ * @param handle the handle of this poll
+ * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
+ */
+ am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check,
+ IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle)
{
- ++mLastInsertedPollHandle;
- if (mLastInsertedPollHandle == MAX_POLLHANDLE)
- {
- mLastInsertedPollHandle = 1;
- }
- if (mLastInsertedPollHandle==lastHandle)
- {
- logError(__func__,"Could not create new polls, too many open!");
- return (am_Error_e::E_NOT_POSSIBLE);
- }
-
- } while (mSetPollKeys.find(mLastInsertedPollHandle) != mSetPollKeys.end());
-
- mSetPollKeys.insert(mLastInsertedPollHandle);
-
- sh_poll_s pollData;
- pollData.pollfdValue.fd = fd;
- pollData.handle = mLastInsertedPollHandle;
- pollData.pollfdValue.events = event;
- pollData.pollfdValue.revents = 0;
- pollData.userData = userData;
- pollData.prepareCB = prepare;
- pollData.firedCB = fired;
- pollData.checkCB = check;
- pollData.dispatchCB = dispatch;
-
- //add new data to the list
- mListPoll.push_back(pollData);
-
- mRecreatePollfds = true;
-
- handle = pollData.handle;
- return (E_OK);
-}
+ if (!fdIsValid(fd))
+ return (E_NON_EXISTENT);
-/**
- * removes a filedescriptor from the poll loop
- * @param handle
- * @return
- */
-am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle)
-{
- mListPoll_t::iterator iterator = mListPoll.begin();
+ //create a new handle for the poll
+ sh_pollHandle_t lastHandle(mLastInsertedPollHandle);
+ do
+ {
+ ++mLastInsertedPollHandle;
+ if (mLastInsertedPollHandle == MAX_POLLHANDLE)
+ {
+ mLastInsertedPollHandle = 1;
+ }
+ if (mLastInsertedPollHandle == lastHandle)
+ {
+ logError("Could not create new polls, too many open!");
+ return (E_NOT_POSSIBLE);
+ }
- for (; iterator != mListPoll.end(); ++iterator)
+ } while (mSetPollKeys.find(mLastInsertedPollHandle) != mSetPollKeys.end());
+
+ mSetPollKeys.insert(mLastInsertedPollHandle);
+
+ sh_poll_s pollData;
+ pollData.pollfdValue.fd = fd;
+ pollData.handle = mLastInsertedPollHandle;
+ pollData.pollfdValue.events = event;
+ pollData.pollfdValue.revents = 0;
+ pollData.userData = userData;
+ pollData.prepareCB = prepare;
+ pollData.firedCB = fired;
+ pollData.checkCB = check;
+ pollData.dispatchCB = dispatch;
+
+ //add new data to the list
+ mListPoll.push_back(pollData);
+
+ mRecreatePollfds = true;
+
+ handle = pollData.handle;
+ return (E_OK);
+ }
+
+ /**
+ * removes a filedescriptor from the poll loop
+ * @param handle
+ * @return
+ */
+ am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle)
{
- if (iterator->handle == handle)
+ mListPoll_t::iterator iterator = mListPoll.begin();
+
+ for (; iterator != mListPoll.end(); ++iterator)
{
- iterator = mListPoll.erase(iterator);
- mSetPollKeys.erase(handle);
- mRecreatePollfds = true;
- return (E_OK);
+ if (iterator->handle == handle)
+ {
+ iterator = mListPoll.erase(iterator);
+ mSetPollKeys.erase(handle);
+ mRecreatePollfds = true;
+ return (E_OK);
+ }
}
+ return (E_UNKNOWN);
}
- return (E_UNKNOWN);
-}
-/**
- * adds a timer to the list of timers. The callback will be fired when the timer is up.
- * This is not a high precise timer, it is very coarse. It is meant to be used for timeouts when waiting
- * for an answer via a filedescriptor.
- * One time timer. If you need again a timer, you need to add a new timer in the callback of the old one.
- * @param timeouts timeouts time until the callback is fired
- * @param callback callback the callback
- * @param handle handle the handle that is created for the timer is returned. Can be used to remove the timer
- * @param userData pointer always passed with the call
- * @return E_OK in case of success
- */
-am_Error_e CAmSocketHandler::addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData)
-{
- assert(!((timeouts.tv_sec==0) && (timeouts.tv_nsec==0)));
- assert(callback!=NULL);
+ /**
+ * adds a timer to the list of timers. The callback will be fired when the timer is up.
+ * This is not a high precise timer, it is very coarse. It is meant to be used for timeouts when waiting
+ * for an answer via a filedescriptor.
+ * One time timer. If you need again a timer, you need to add a new timer in the callback of the old one.
+ * @param timeouts timeouts time until the callback is fired
+ * @param callback callback the callback
+ * @param handle handle the handle that is created for the timer is returned. Can be used to remove the timer
+ * @param userData pointer always passed with the call
+ * @return E_OK in case of success
+ */
+ am_Error_e CAmSocketHandler::addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
+ {
+ assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0)));
+ assert(callback!=NULL);
- sh_timer_s timerItem;
+ mListTimer.emplace_back();
+ sh_timer_s & timerItem = mListTimer.back();
- //create a new handle for the timer
- sh_timerHandle_t lastTimerHandle(mLastInsertedHandle);
- do
- {
- ++mLastInsertedHandle;
- if (mLastInsertedHandle == MAX_TIMERHANDLE)
- {
- mLastInsertedHandle = 1;
- }
- if (lastTimerHandle==mLastInsertedHandle)
- {
- logError(__func__,"Could not create new timers, too many open!");
- return (am_Error_e::E_NOT_POSSIBLE);
- }
-
- } while (mSetTimerKeys.find(mLastInsertedHandle) != mSetTimerKeys.end());
-
- mSetTimerKeys.insert(mLastInsertedHandle);
- handle=mLastInsertedHandle;
- timerItem.handle = handle;
- timerItem.countdown = timeouts;
- timerItem.callback = callback;
- timerItem.userData = userData;
-
- mListTimer.push_back(timerItem);
-
- //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
- timespec currentTime;
- clock_gettime(CLOCK_MONOTONIC, &currentTime);
- if (!mDispatchDone) //the mainloop is started
- timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
-
- mListActiveTimer.push_back(timerItem);
- mListActiveTimer.sort(compareCountdown);
- return (E_OK);
-}
+#ifndef WITH_TIMERFD
+ //create a new handle for the timer
+ sh_timerHandle_t lastTimerHandle(mLastInsertedHandle);
+ do
+ {
+ ++mLastInsertedHandle;
+ if (mLastInsertedHandle == MAX_TIMERHANDLE)
+ {
+ mLastInsertedHandle = 1;
+ }
+ if (lastTimerHandle==mLastInsertedHandle)
+ {
+ logError("Could not create new timers, too many open!");
+ mListTimer.pop_back();
+ return (E_NOT_POSSIBLE);
+ }
-/**
- * removes a timer from the list of timers
- * @param handle the handle to the timer
- * @return E_OK in case of success, E_UNKNOWN if timer was not found.
- */
-am_Error_e CAmSocketHandler::removeTimer(const sh_timerHandle_t handle)
-{
- assert(handle!=0);
+ }while (mSetTimerKeys.find(mLastInsertedHandle) != mSetTimerKeys.end());
- //stop the current timer
- stopTimer(handle);
+ mSetTimerKeys.insert(mLastInsertedHandle);
+ handle=mLastInsertedHandle;
- std::list<sh_timer_s>::iterator it(mListTimer.begin());
- for (; it != mListTimer.end(); ++it)
- {
- if (it->handle == handle)
+ timerItem.countdown = timeouts;
+ timerItem.callback = callback;
+ timerItem.userData = userData;
+
+ timerItem.handle = handle;
+
+ //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
+ timespec currentTime;
+ clock_gettime(CLOCK_MONOTONIC, &currentTime);
+ if (!mDispatchDone)//the mainloop is started
+ timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
+ mListTimer.push_back(timerItem);
+ mListActiveTimer.push_back(timerItem);
+ mListActiveTimer.sort(compareCountdown);
+ return (E_OK);
+
+#else
+ timerItem.countdown.it_value = timeouts;
+ if(repeats)
+ timerItem.countdown.it_interval = timeouts;
+ else
+ {
+ timespec zero;
+ zero.tv_sec = 0;
+ zero.tv_nsec = 0;
+ timerItem.countdown.it_interval = zero;
+ }
+
+ timerItem.callback = callback;
+ timerItem.userData = userData;
+ timerItem.fd = -1;
+ am_Error_e err = createTimeFD(timerItem.countdown, timerItem.fd);
+ if (err != E_OK)
{
- it = mListTimer.erase(it);
- mSetTimerKeys.erase(handle);
- return (E_OK);
+ mListTimer.pop_back();
+ return err;
}
+ mTimerCallbackT.emplace_back(callback);
+
+ err = addFDPoll(timerItem.fd, POLLIN, NULL, &mTimerCallbackT.back(), &mTimerCallbackT.back(), NULL, NULL, handle);
+ if (E_OK == err)
+ {
+ timerItem.handle = handle;
+ }
+ else
+ {
+ mTimerCallbackT.pop_back();
+ mListTimer.pop_back();
+ }
+ return err;
+#endif
+
}
- return (E_UNKNOWN);
-}
-/**
- * restarts a timer and updates with a new interva
- * @param handle handle to the timer
- * @param timeouts new timout time
- * @return E_OK on success, E_NON_EXISTENT if the handle was not found
- */
-am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const timespec timeouts)
-{
- //update the mList ....
- sh_timer_s timerItem;
- std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
- bool found(false);
- for (; it != mListTimer.end(); ++it)
+ /**
+ * removes a timer from the list of timers
+ * @param handle the handle to the timer
+ * @return E_OK in case of success, E_UNKNOWN if timer was not found.
+ */
+ am_Error_e CAmSocketHandler::removeTimer(const sh_timerHandle_t handle)
{
- if (it->handle == handle)
+ assert(handle != 0);
+
+ //stop the current timer
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ break;
+ }
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
+
+ close(it->fd);
+ mListTimer.erase(it);
+ return removeFDPoll(handle);
+#else
+ stopTimer(handle);
+ std::list<sh_timer_s>::iterator it(mListTimer.begin());
+ for (; it != mListTimer.end(); ++it)
{
- it->countdown = timeouts;
- timerItem = *it;
- found = true;
- break;
+ if (it->handle == handle)
+ {
+ it = mListTimer.erase(it);
+ mSetTimerKeys.erase(handle);
+ return (E_OK);
+ }
}
+ return (E_UNKNOWN);
+#endif
}
- if (!found)
+
+ /**
+ * restarts a timer and updates with a new interva
+ * @param handle handle to the timer
+ * @param timeouts new timout time
+ * @return E_OK on success, E_NON_EXISTENT if the handle was not found
+ */
+ am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const timespec & timeouts)
+ {
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ break;
+ }
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
+
+ if (it->countdown.it_interval.tv_nsec != 0 || it->countdown.it_interval.tv_sec != 0)
+ it->countdown.it_interval = timeouts;
+ it->countdown.it_value = timeouts;
+
+ if (!fdIsValid(it->fd))
+ {
+ am_Error_e err = createTimeFD(it->countdown, it->fd);
+ if (err != E_OK)
+ return err;
+ }
+ else
+ {
+ if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
+ {
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
+ }
+ }
+#else
+
+ //update the mList ....
+ sh_timer_s timerItem;
+ std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
+ bool found(false);
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ {
+ it->countdown = timeouts;
+ timerItem = *it;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
return (E_NON_EXISTENT);
- found = false;
+ found = false;
- //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
- timespec currentTime, timeoutsCorrected;
- currentTime.tv_nsec=timeoutsCorrected.tv_nsec=0;
- currentTime.tv_sec=timeoutsCorrected.tv_sec=0;
- clock_gettime(CLOCK_MONOTONIC, &currentTime);
- if (!mDispatchDone) //the mainloop is started
+ //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
+ timespec currentTime, timeoutsCorrected;
+ currentTime.tv_nsec=timeoutsCorrected.tv_nsec=0;
+ currentTime.tv_sec=timeoutsCorrected.tv_sec=0;
+ clock_gettime(CLOCK_MONOTONIC, &currentTime);
+ if (!mDispatchDone)//the mainloop is started
timeoutsCorrected = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
- for (; activeIt != mListActiveTimer.end(); ++activeIt)
- {
- if (activeIt->handle == handle)
+ for (; activeIt != mListActiveTimer.end(); ++activeIt)
{
- activeIt->countdown = timeoutsCorrected;
- found = true;
- break;
+ if (activeIt->handle == handle)
+ {
+ activeIt->countdown = timeoutsCorrected;
+ found = true;
+ break;
+ }
}
- }
- if (!found)
+ if (!found)
timerItem.countdown = timeoutsCorrected;
- mListActiveTimer.push_back(timerItem);
+ mListActiveTimer.push_back(timerItem);
- mListActiveTimer.sort(compareCountdown);
- return (E_OK);
-}
+ mListActiveTimer.sort(compareCountdown);
-/**
- * restarts a timer with the original value
- * @param handle
- * @return E_OK on success, E_NON_EXISTENT if the handle was not found
- */
-am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle)
-{
- sh_timer_s timerItem; //!<the original timer value
- //find the original value
- std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
- bool found(false);
- for (; it != mListTimer.end(); ++it)
+#endif
+ return (E_OK);
+ }
+
+ /**
+ * restarts a timer with the original value
+ * @param handle
+ * @return E_OK on success, E_NON_EXISTENT if the handle was not found
+ */
+ am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle)
{
- if (it->handle == handle)
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
{
- timerItem = *it;
- found = true;
- break;
+ if (it->handle == handle)
+ break;
}
- }
- if (!found)
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
+
+ if (!fdIsValid(it->fd))
+ {
+ am_Error_e err = createTimeFD(it->countdown, it->fd);
+ if (err != E_OK)
+ return err;
+ }
+ else
+ {
+ if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
+ {
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
+ }
+ }
+#else
+
+ sh_timer_s timerItem; //!<the original timer value
+ //find the original value
+ std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
+ bool found(false);
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ {
+ timerItem = *it;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
return (E_NON_EXISTENT);
- found = false;
+ found = false;
- //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
- timespec currentTime, timeoutsCorrected;
- clock_gettime(CLOCK_MONOTONIC, &currentTime);
- if (!mDispatchDone) //the mainloop is started
- {
- timeoutsCorrected = timespecAdd(timerItem.countdown, timespecSub(currentTime, mStartTime));
- timerItem.countdown = timeoutsCorrected;
- }
+ //we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
+ timespec currentTime, timeoutsCorrected;
+ clock_gettime(CLOCK_MONOTONIC, &currentTime);
+ if (!mDispatchDone)//the mainloop is started
+ {
+ timeoutsCorrected = timespecAdd(timerItem.countdown, timespecSub(currentTime, mStartTime));
+ timerItem.countdown = timeoutsCorrected;
+ }
- for (; activeIt != mListActiveTimer.end(); ++activeIt)
- {
- if (activeIt->handle == handle)
+ for (; activeIt != mListActiveTimer.end(); ++activeIt)
{
- activeIt->countdown = timerItem.countdown;
- found = true;
- break;
+ if (activeIt->handle == handle)
+ {
+ activeIt->countdown = timerItem.countdown;
+ found = true;
+ break;
+ }
}
- }
- if (!found)
+ if (!found)
mListActiveTimer.push_back(timerItem);
- mListActiveTimer.sort(compareCountdown);
-
- return (E_OK);
-}
+ mListActiveTimer.sort(compareCountdown);
+#endif
+ return (E_OK);
+ }
-/**
- * stops a timer
- * @param handle
- * @return E_OK on success, E_NON_EXISTENT if the handle was not found
- */
-am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle)
-{
- //go through the list and remove the timer with the handle
- std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
- for (; it != mListActiveTimer.end(); ++it)
+ /**
+ * stops a timer
+ * @param handle
+ * @return E_OK on success, E_NON_EXISTENT if the handle was not found
+ */
+ am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle)
{
- if (it->handle == handle)
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
{
- it = mListActiveTimer.erase(it);
- return (E_OK);
+ if (it->handle == handle)
+ break;
}
- }
- return (E_NON_EXISTENT);
-}
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
-/**
- * updates the eventFlags of a poll
- * @param handle
- * @param events
- * @return @return E_OK on succsess, E_NON_EXISTENT if fd was not found
- */
-am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, const short events)
-{
- mListPoll_t::iterator iterator = mListPoll.begin();
+ itimerspec countdown = it->countdown;
+ countdown.it_value.tv_nsec = 0;
+ countdown.it_value.tv_sec = 0;
- for (; iterator != mListPoll.end(); ++iterator)
- {
- if (iterator->handle == handle)
+ if (timerfd_settime(it->fd, 0, &countdown, NULL))
{
- iterator->pollfdValue.events = events;
- mRecreatePollfds = true;
- return (E_OK);
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
}
+#else
+ //go through the list and remove the timer with the handle
+ std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
+ for (; it != mListActiveTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ {
+ it = mListActiveTimer.erase(it);
+ return (E_OK);
+ }
+ }
+ return (E_NON_EXISTENT);
+#endif
}
- return (E_UNKNOWN);
-}
-/**
- * checks if a filedescriptor is validCAmShSubstractTime
- * @param fd the filedescriptor
- * @return true if the fd is valid
- */
-bool CAmSocketHandler::fdIsValid(const int fd) const
-{
- return (fcntl(fd, F_GETFL) != -1 || errno != EBADF);
-}
+ /**
+ * updates the eventFlags of a poll
+ * @param handle
+ * @param events
+ * @return @return E_OK on succsess, E_NON_EXISTENT if fd was not found
+ */
+ am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, const short events)
+ {
+ mListPoll_t::iterator iterator = mListPoll.begin();
-/**
- * timer is up.
- */
-void CAmSocketHandler::timerUp()
-{
- //find out the timedifference to starttime
- timespec currentTime, diffTime;
- clock_gettime(CLOCK_MONOTONIC, &currentTime);
- diffTime = timespecSub(currentTime, mStartTime);
+ for (; iterator != mListPoll.end(); ++iterator)
+ {
+ if (iterator->handle == handle)
+ {
+ iterator->pollfdValue.events = events;
+ mRecreatePollfds = true;
+ return (E_OK);
+ }
+ }
+ return (E_UNKNOWN);
+ }
- //now we need to substract the diffTime from all timers and see if they are up
- std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownUp(diffTime));
+ /**
+ * checks if a filedescriptor is validCAmShSubstractTime
+ * @param fd the filedescriptor
+ * @return true if the fd is valid
+ */
+ bool CAmSocketHandler::fdIsValid(const int fd) const
+ {
+ return (fcntl(fd, F_GETFL) != -1 || errno != EBADF);
+ }
- //copy all fired timers into a list
- std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
+#ifndef WITH_TIMERFD
+ /**
+ * timer is up.
+ */
+ void CAmSocketHandler::timerUp()
+ {
+ //find out the timedifference to starttime
+ timespec currentTime, diffTime;
+ clock_gettime(CLOCK_MONOTONIC, &currentTime);
+ diffTime = timespecSub(currentTime, mStartTime);
- //erase all fired timers
- std::list<sh_timer_s>::iterator it(overflowIter.base());
- mListActiveTimer.erase(mListActiveTimer.begin(), it);
+ //now we need to substract the diffTime from all timers and see if they are up
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownUp(diffTime));
- //call the callbacks for the timers
- std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
-}
+ //copy all fired timers into a list
+ std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
-/**
- * correct timers and fire the ones who are up
- */
-void CAmSocketHandler::timerCorrection()
-{
- //get the current time and calculate the correction value
- timespec currentTime, correctionTime;
- clock_gettime(CLOCK_MONOTONIC, &currentTime);
- correctionTime = timespecSub(currentTime, mStartTime);
- mStartTime = currentTime;
+ //erase all fired timers
+ std::list<sh_timer_s>::iterator it(overflowIter.base());
+ mListActiveTimer.erase(mListActiveTimer.begin(), it);
- if (!mListActiveTimer.empty())
+ //call the callbacks for the timers
+ std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ }
+
+ /**
+ * correct timers and fire the ones who are up
+ */
+ void CAmSocketHandler::timerCorrection()
{
+ //get the current time and calculate the correction value
+ timespec currentTime, correctionTime;
+ clock_gettime(CLOCK_MONOTONIC, &currentTime);
+ correctionTime = timespecSub(currentTime, mStartTime);
+ mStartTime = currentTime;
- //subtract the correction value from all items in the list
- std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
+ if (!mListActiveTimer.empty())
+ {
- //find the last occurrence of zero -> timer overflowed
- std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownZero());
+ //subtract the correction value from all items in the list
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
- //only if a timer overflowed
- if (overflowIter != mListActiveTimer.rend())
- {
- //copy all timers that need to be called to a new list
- std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
+ //find the last occurrence of zero -> timer overflowed
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownZero());
+
+ //only if a timer overflowed
+ if (overflowIter != mListActiveTimer.rend())
+ {
+ //copy all timers that need to be called to a new list
+ std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
- //erase all fired timers
- std::list<sh_timer_s>::iterator it(overflowIter.base());
- mListActiveTimer.erase(mListActiveTimer.begin(), it);
+ //erase all fired timers
+ std::list<sh_timer_s>::iterator it(overflowIter.base());
+ mListActiveTimer.erase(mListActiveTimer.begin(), it);
- //call the callbacks for the timers
- std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ //call the callbacks for the timers
+ std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ }
+ }
+ }
+#endif
+ /**
+ * is used to set the pointer for the ppoll command
+ * @param buffertime
+ * @return
+ */
+ inline timespec* CAmSocketHandler::insertTime(timespec& buffertime)
+ {
+#ifndef WITH_TIMERFD
+ if (!mListActiveTimer.empty())
+ {
+ buffertime = mListActiveTimer.front().countdown;
+ return (&buffertime);
+ }
+ else
+#endif
+ {
+ return (NULL);
}
}
-}
-void CAmSocketHandler::exit_mainloop()
-{
- //end the while loop
- stop_listening();
+#ifdef WITH_TIMERFD
+ am_Error_e CAmSocketHandler::createTimeFD(const itimerspec & timeouts, int & fd)
+ {
+ fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (fd <= 0)
+ {
+ logError("Failed to create timer");
+ return E_NOT_POSSIBLE;
+ }
+ if (fcntl(fd, F_SETFL, O_NONBLOCK))
+ {
+ logError("Failed to set to non blocking mode");
+ return E_NOT_POSSIBLE;
+ }
- //fire the ending filedescriptor
- int p(1);
- ssize_t result = write(mPipe[1], &p, sizeof(p));
-}
+ if (timerfd_settime(fd, 0, &timeouts, NULL))
+ {
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
+ }
+ return E_OK;
+ }
+#endif
-/**
- * is used to set the pointer for the ppoll command
- * @param buffertime
- * @return
- */
-inline timespec* CAmSocketHandler::insertTime(timespec& buffertime)
-{
- if (!mListActiveTimer.empty())
+ void CAmSocketHandler::CAmShCallFire::operator()(sh_poll_s& row)
{
- buffertime = mListActiveTimer.front().countdown;
- return (&buffertime);
+ try
+ {
+ row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in FireCallback,caught", e.what());
+ }
}
- else
+
+ void CAmSocketHandler::CAmShCallPrep::operator()(sh_poll_s& row)
{
- return (NULL);
+ if (row.prepareCB)
+ {
+ try
+ {
+ row.prepareCB->Call(row.handle, row.userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in Preparecallback,caught", e.what());
+ }
+ }
}
-}
-
-void CAmSocketHandler::CAmShCallFire::operator()(sh_poll_s& row)
-{
- try
- {
- row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
- }
- catch (std::exception& e)
- {
- logError("Sockethandler: Exception in FireCallback,caught",e.what());
- }
-}
-
-void CAmSocketHandler::CAmShCallPrep::operator()(sh_poll_s& row)
-{
- if (row.prepareCB)
- {
- try
- {
- row.prepareCB->Call(row.handle, row.userData);
- }
- catch (std::exception& e)
- {
- logError("Sockethandler: Exception in Preparecallback,caught",e.what());
- }
- }
-}
-void CAmSocketHandler::CAmShCallTimer::operator()(sh_timer_s& row)
-{
- try
- {
- row.callback->Call(row.handle, row.userData);
- }
- catch (std::exception& e)
- {
- logError("Sockethandler: Exception in Timercallback,caught",e.what());
- }
-}
+ void CAmSocketHandler::CAmShCallTimer::operator()(sh_timer_s& row)
+ {
+ try
+ {
+ row.callback->Call(row.handle, row.userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in Timercallback,caught", e.what());
+ }
+ }
-void CAmSocketHandler::CAmShCopyPollfd::operator()(const sh_poll_s& row)
-{
- pollfd temp = row.pollfdValue;
- temp.revents = 0;
- mArray.push_back(temp);
-}
+ void CAmSocketHandler::CAmShCopyPollfd::operator()(const sh_poll_s& row)
+ {
+ pollfd temp = row.pollfdValue;
+ temp.revents = 0;
+ mArray.push_back(temp);
+ }
+#ifndef WITH_TIMERFD
bool CAmSocketHandler::CAmShCountdownUp::operator()(const sh_timer_s& row)
{
- timespec sub = timespecSub(row.countdown, mDiffTime);
- if (sub.tv_nsec == 0 && sub.tv_sec == 0)
- return (true);
- return (false);
+ timespec sub = timespecSub(row.countdown, mDiffTime);
+ if (sub.tv_nsec == 0 && sub.tv_sec == 0)
+ return (true);
+ return (false);
}
bool CAmSocketHandler::CAmShCountdownZero::operator()(const sh_timer_s& row)
{
- if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
- return (true);
- return (false);
+ if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
+ return (true);
+ return (false);
}
-
+#endif
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 33433ee..b89daa1 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,7 +59,10 @@ option ( WITH_SHARED_UTILITIES
option ( WITH_SHARED_CORE
"Build audio manager core as dynamic library" OFF)
-
+
+option ( WITH_TIMERFD
+ "Build with the linux specific TIMERFD feature to support timing without using signals" ON)
+
set(DBUS_SERVICE_PREFIX "org.genivi.audiomanager"
CACHE PROPERTY "The dbus service prefix for the AM - only changable for legacy dbus")
@@ -219,6 +222,7 @@ message(STATUS "WITH_CAPI_WRAPPER = ${WITH_CAPI_WRAPPER}")
message(STATUS "WITH_DBUS_WRAPPER = ${WITH_DBUS_WRAPPER}")
message(STATUS "WITH_SHARED_UTILITIES = ${WITH_SHARED_UTILITIES}")
message(STATUS "WITH_SHARED_CORE = ${WITH_SHARED_CORE}")
+message(STATUS "WITH_TIMERFD = ${WITH_TIMERFD}")
message(STATUS "DYNAMIC_ID_BOUNDARY = ${DYNAMIC_ID_BOUNDARY}")
message(STATUS "LIB_INSTALL_SUFFIX = ${LIB_INSTALL_SUFFIX}")
message(STATUS "TEST_EXECUTABLE_INSTALL_PATH = ${TEST_EXECUTABLE_INSTALL_PATH}")
diff --git a/cmake/AudioManagerUtilitiesConfig.cmake.in b/cmake/AudioManagerUtilitiesConfig.cmake.in
index acca825..11ebf55 100644
--- a/cmake/AudioManagerUtilitiesConfig.cmake.in
+++ b/cmake/AudioManagerUtilitiesConfig.cmake.in
@@ -7,6 +7,7 @@ set(WITH_CAPI_WRAPPER "@WITH_CAPI_WRAPPER@")
set(WITH_DBUS_WRAPPER "@WITH_DBUS_WRAPPER@")
set(WITH_SYSTEMD_WATCHDOG "@WITH_SYSTEMD_WATCHDOG@")
set(WITH_DLT "@WITH_DLT@")
+set(WITH_TIMERFD "@WITH_TIMERFD@")
if(WITH_SYSTEMD_WATCHDOG)
diff --git a/cmake/config.cmake.in b/cmake/config.cmake.in
index da64732..1501393 100644
--- a/cmake/config.cmake.in
+++ b/cmake/config.cmake.in
@@ -9,6 +9,7 @@
#cmakedefine WITH_TELNET
#cmakedefine GLIB_DBUS_TYPES_TOLERANT
#cmakedefine WITH_SYSTEMD_WATCHDOG
+#cmakedefine WITH_TIMERFD
#cmakedefine DEFAULT_PLUGIN_DIR "@DEFAULT_PLUGIN_DIR@"
#cmakedefine DEFAULT_PLUGIN_COMMAND_DIR "@DEFAULT_PLUGIN_COMMAND_DIR@"