summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AudioManagerDaemon/src/CAmSocketHandler.cpp244
-rw-r--r--AudioManagerDaemon/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp68
-rw-r--r--CMakeLists.txt3
-rw-r--r--PluginControlInterface/test/CAmControlReceiverShadowTest.cpp2
-rw-r--r--PluginRoutingInterfaceAsync/test/CAmRoutingReceiverAsync.cpp5
-rw-r--r--cmake/config.cmake1
-rw-r--r--include/shared/CAmSerializer.h2
-rw-r--r--include/shared/CAmSocketHandler.h293
8 files changed, 344 insertions, 274 deletions
diff --git a/AudioManagerDaemon/src/CAmSocketHandler.cpp b/AudioManagerDaemon/src/CAmSocketHandler.cpp
index 2ae1337..a6c4be9 100644
--- a/AudioManagerDaemon/src/CAmSocketHandler.cpp
+++ b/AudioManagerDaemon/src/CAmSocketHandler.cpp
@@ -25,15 +25,12 @@
#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/poll.h>
-#include <algorithm>
#include <time.h>
+#include <algorithm>
#include <features.h>
#include <csignal>
#include "shared/CAmDltWrapper.h"
-//todo: implement time correction if timer was interrupted by call
-//todo: change hitlist to a list that holds all information, because entering and removing items will be cheaper than with std::vector
-
namespace am
{
@@ -41,14 +38,11 @@ CAmSocketHandler::CAmSocketHandler() :
mListPoll(), //
mListTimer(), //
mListActiveTimer(), //
- mNextTimer(), //
mLastInsertedHandle(0), //
mLastInsertedPollHandle(0), //
mRecreatePollfds(true), //
- mTimeout()
+ mStartTime()
{
- mTimeout.tv_nsec = -1;
- mTimeout.tv_sec = -1;
gDispatchDone = 0;
}
@@ -64,10 +58,6 @@ void CAmSocketHandler::start_listenting()
{
gDispatchDone = 0;
int16_t pollStatus;
- std::list<int16_t> hitList;
-
- //init the timer
- initTimer();
//prepare the signalmask
sigset_t sigmask;
@@ -78,16 +68,11 @@ void CAmSocketHandler::start_listenting()
sigaddset(&sigmask, SIGHUP);
sigaddset(&sigmask, SIGQUIT);
+ clock_gettime(CLOCK_MONOTONIC, &mStartTime);
while (!gDispatchDone)
{
//first we go through the registered filedescriptors and check if someone needs preparation:
- mListPoll_t::iterator prepIter = mListPoll.begin();
- IAmShPollPrepare *prep = NULL;
- for (; prepIter != mListPoll.end(); ++prepIter)
- {
- if ((prep = prepIter->prepareCB) != NULL)
- prep->Call(prepIter->handle, prepIter->userData);
- }
+ std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCallPrep());
if (mRecreatePollfds)
{
@@ -97,8 +82,10 @@ void CAmSocketHandler::start_listenting()
mRecreatePollfds = false;
}
+ if (!mListActiveTimer.empty())
+ timerCorrection();
+
//block until something is on a filedescriptor
-#ifdef WITH_PPOLL
timespec buffertime;
if ((pollStatus = ppoll(&mfdPollingArray[0], mfdPollingArray.size(), insertTime(buffertime), &sigmask)) < 0)
@@ -115,84 +102,41 @@ void CAmSocketHandler::start_listenting()
}
}
-#else
- //sigprocmask (SIG_SETMASK, &mask, &oldmask);
- if((pollStatus=poll(&mfdPollingArray[0],mfdPollingArray.size(),timespec2ms(mTimeout)))<0)
- {
-
- if(errno==EINTR)
- {
- //a signal was received, that means it's time to go...
- //todo: add things to do here before going to sleep
- exit(0);
- }
- logError("SocketHandler::start_listenting poll returned with error",errno);
- exit(0);
- }
- //sigprocmask (SIG_SETMASK, &oldmask, NULL);
-#endif
-
+ clock_gettime(CLOCK_MONOTONIC, &mStartTime);
if (pollStatus != 0) //only check filedescriptors if there was a change
{
//todo: here could be a timer that makes sure naughty plugins return!
//freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
- mListPoll_t listPoll(mListPoll);
+ std::list<sh_poll_s> listPoll;
+ mListPoll_t::iterator listmPollIt;
- //get all indexes of the fired events and save them int hitList
- hitList.clear();
+ //remove all filedescriptors who did not fire
std::vector<pollfd>::iterator it = mfdPollingArray.begin();
do
{
- it = std::find_if(it, mfdPollingArray.end(), onlyFiredEvents);
+ it = std::find_if(it, mfdPollingArray.end(), eventFired);
if (it != mfdPollingArray.end())
- hitList.push_back(std::distance(mfdPollingArray.begin(), it++));
-
+ {
+ 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 for all matched events, but only if callback is not zero!
- std::list<int16_t>::iterator hListIt = hitList.begin();
- for (; hListIt != hitList.end(); ++hListIt)
- {
- IAmShPollFired* fire = NULL;
- if ((fire = listPoll.at(*hListIt).firedCB) != NULL)
- fire->Call(mfdPollingArray.at(*hListIt), listPoll.at(*hListIt).handle, listPoll.at(*hListIt).userData);
- }
+ //stage 1, call firedCB
+ std::for_each(listPoll.begin(), listPoll.end(), CAmShCallFire());
- //stage 2, lets ask around if some dispatching is necessary, if not, they are taken from the hitlist
- hListIt = hitList.begin();
- for (; hListIt != hitList.end(); ++hListIt)
- {
- IAmShPollCheck* check = NULL;
- if ((check = listPoll.at(*hListIt).checkCB) != NULL)
- {
- if (!check->Call(listPoll.at(*hListIt).handle, listPoll.at(*hListIt).userData))
- {
- hListIt = hitList.erase(hListIt);
- }
- }
- }
+ //stage 2, lets ask around if some dispatching is necessary, the ones who need stay on the list
+ listPoll.remove_if(noDispatching);
//stage 3, the ones left need to dispatch, we do this as long as there is something to dispatch..
do
{
- hListIt = hitList.begin();
- for (; hListIt != hitList.end(); ++hListIt)
- {
- IAmShPollDispatch *dispatch = NULL;
- if ((dispatch = listPoll.at(*hListIt).dispatchCB) != NULL)
- {
- if (!dispatch->Call(listPoll.at(*hListIt).handle, listPoll.at(*hListIt).userData))
- {
- hListIt = hitList.erase(hListIt);
- }
- }
- else //there is no dispatch function, so we just remove the file from the list...
- {
- hListIt = hitList.erase(hListIt);
- }
- }
- } while (!hitList.empty());
+ listPoll.remove_if(dispatchingFinished);
+ } while (!listPoll.empty());
}
else //Timerevent
@@ -288,20 +232,16 @@ am_Error_e CAmSocketHandler::addTimer(const timespec timeouts, IAmShTimerCallBac
sh_timer_s timerItem;
//create a new handle for the timer
- handle = ++mLastInsertedHandle; //todo: overflow ruling !
+ handle = ++mLastInsertedHandle; //todo: overflow ruling !o
timerItem.handle = handle;
timerItem.countdown = timeouts;
timerItem.timeout = timeouts;
timerItem.callback = callback;
timerItem.userData = userData;
- //add timer to the list
- mListActiveTimer.push_back(timerItem);
mListTimer.push_back(timerItem);
-
- //very important: sort the list so that the smallest value is front
+ mListActiveTimer.push_back(timerItem);
mListActiveTimer.sort(compareCountdown);
- mTimeout = mListActiveTimer.front().countdown;
return (E_OK);
}
@@ -348,16 +288,11 @@ am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle, const t
}
}
- if (timeouts.tv_nsec != -1 && timeouts.tv_sec != -1)
- {
- timerItem.timeout = timeouts;
- }
+ timerItem.timeout=timeouts;
+ timerItem.countdown=timeouts;
mListActiveTimer.push_back(timerItem);
-
- //very important: sort the list so that the smallest value is front
mListActiveTimer.sort(compareCountdown);
- mTimeout = mListActiveTimer.front().countdown;
return (E_OK);
}
@@ -370,15 +305,6 @@ am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle)
if (it->handle == handle)
{
it = mListActiveTimer.erase(it);
- if (!mListActiveTimer.empty())
- {
- mTimeout = mListActiveTimer.front().countdown;
- }
- else
- {
- mTimeout.tv_nsec = -1;
- mTimeout.tv_sec = -1;
- }
return (E_OK);
}
}
@@ -387,7 +313,9 @@ am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle)
/**
* updates the eventFlags of a poll
- * @param handle
+ * @param handle buffertime.tv_nsec = mTimeout.tv_nsec;
+ buffertime.tv_sec = mTimeout.tv_sec;
+ return ((mTimeout.tv_nsec == -1 && mTimeout.tv_sec == -1) ? NULL : &buffertime);
* @param events
* @return @return E_OK on succsess, E_NON_EXISTENT if fd was not found
*/
@@ -408,7 +336,7 @@ am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, cons
}
/**
- * checks if a filedescriptor is valid
+ * checks if a filedescriptor is validCAmShSubstractTime
* @param fd the filedescriptor
* @return true if the fd is valid
*/
@@ -418,43 +346,25 @@ bool CAmSocketHandler::fdIsValid(const int fd) const
}
/**
- * whenever a timer is up, this function needs to be called.
- * Removes the fired timer, calls the callback and resets mTimeout
+ * timer is up.
*/
void CAmSocketHandler::timerUp()
{
- //first fire the event
- mListActiveTimer.front().callback->Call(mListActiveTimer.front().handle, mListActiveTimer.front().userData);
+ //first we need to correct all the countdown values by the one who fired
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(mListActiveTimer.begin()->countdown));
- //then remove the first timer, the one who fired
- mListActiveTimer.pop_front();
- if (!mListActiveTimer.empty())
- {
- //substract the old value from all timers in the list
- std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(mTimeout));
- mTimeout = mListActiveTimer.front().countdown;
- }
- else
- {
- mTimeout.tv_nsec = -1;
- mTimeout.tv_sec = -1;
- }
-}
+ //then find the last value that is zero. Since the first value is subtracted, we will always have the first one
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownUp());
-/**
- * init the timers
- */
-void CAmSocketHandler::initTimer()
-{
- if (!mListActiveTimer.empty())
- {
- mTimeout = mListActiveTimer.front().countdown;
- }
- else
- {
- mTimeout.tv_nsec = -1;
- mTimeout.tv_sec = -1;
- }
+ //copy all fired timers into a 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);
+
+ //call the callbacks for the timers
+ std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
}
/**
@@ -467,36 +377,58 @@ inline int CAmSocketHandler::timespec2ms(const timespec & time)
return ((time.tv_nsec == -1 && time.tv_sec == -1) ? -1 : time.tv_sec * 1000 + time.tv_nsec / 1000000);
}
-inline timespec* CAmSocketHandler::insertTime(timespec& buffertime)
+/**
+ * correct timers
+ */
+void CAmSocketHandler::timerCorrection()
{
- buffertime.tv_nsec = mTimeout.tv_nsec;
- buffertime.tv_sec = mTimeout.tv_sec;
- return ((mTimeout.tv_nsec == -1 && mTimeout.tv_sec == -1) ? NULL : &buffertime);
+ //get the current time and calculate the correction value
+ timespec currentTime, correctionTime;
+ clock_gettime(CLOCK_MONOTONIC, &currentTime);
+ correctionTime = timespecSub(currentTime, mStartTime);
+
+ //subtract the correction value from all items in the list
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
+
+ //find the last occurrence of zero -> timer overflowed
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownUp());
+
+ //only if a timer overflowed
+ if (overflowIter != mListActiveTimer.rend())
+ {
+ //copy all timer 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);
+
+ //call the callbacks for the timers
+ std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ }
}
-/**
- * functor to easy substract from each countdown
- * @param t value to substract from
- */
-void CAmSocketHandler::CAmShSubstractTime::operator ()(sh_timer_s & t) const
+inline timespec* CAmSocketHandler::insertTime(timespec& buffertime)
{
- int val = 0;
- if ((val = t.countdown.tv_nsec - param.tv_nsec) < 0)
+ if (!mListActiveTimer.empty())
{
- t.countdown.tv_nsec = 1000000000 + val;
- t.countdown.tv_sec--;
+ buffertime = mListActiveTimer.front().countdown;
+ return (&buffertime);
}
else
{
- t.countdown.tv_nsec = val;
+ return (NULL);
}
- (t.countdown.tv_sec - param.tv_sec) < 0 ? 0 : (t.countdown.tv_sec -= param.tv_sec);
}
-void CAmSocketHandler::CAmShCopyPollfd::operator ()(const sh_poll_s & row)
+/**
+ * functor to easy substract from each countdown
+ * @param t value to substract from
+ */
+void CAmSocketHandler::CAmShSubstractTime::operator ()(sh_timer_s & t) const
{
- pollfd temp = row.pollfdValue;
- temp.revents = 0;
- mArray.push_back(temp);
+ t.countdown = timespecSub(t.countdown, param);
}
+
}
+
diff --git a/AudioManagerDaemon/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp b/AudioManagerDaemon/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
index dadcd1f..19e4772 100644
--- a/AudioManagerDaemon/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
+++ b/AudioManagerDaemon/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
@@ -68,22 +68,18 @@ void am::CAmTimerCb::timer1Callback(sh_timerHandle_t handle, void* userData)
timespec timeout;
timeout.tv_nsec = 0;
timeout.tv_sec = 1;
- IAmShTimerCallBack *buf = &pTimer1Callback;
- sh_timerHandle_t handle_;
- mSocketHandler->addTimer(timeout, buf, handle_, NULL);
+ mSocketHandler->restartTimer(handle,timeout);
}
void am::CAmTimerCb::timer2Callback(sh_timerHandle_t handle, void* userData)
{
(void) handle;
(void) userData;
- std::cout << "callback2 called" << std::endl;
+ // std::cout << "callback2 called" << std::endl;
timespec timeout;
- timeout.tv_nsec = 0;
- timeout.tv_sec = 1;
- IAmShTimerCallBack *buf = &pTimer2Callback;
- sh_timerHandle_t handle_;
- mSocketHandler->addTimer(timeout, buf, handle_, NULL);
+ timeout.tv_nsec = 011110000;
+ timeout.tv_sec = 0;
+ mSocketHandler->restartTimer(handle,timeout);
}
void am::CAmTimerCb::timer3Callback(sh_timerHandle_t, void* userData)
@@ -119,6 +115,34 @@ void* playWithUnixSocketServer(void* data)
return (NULL);
}
+TEST(CAmSocketHandlerTest,playWithTimers)
+{
+ gDispatchDone = 0;
+ CAmSocketHandler myHandler;
+ CAmTimerCb testCallback(&myHandler);
+ timespec timeoutTime, timeout2, timeout3, timeout4;
+ timeoutTime.tv_sec = 1;
+ timeoutTime.tv_nsec = 02223234;
+ timeout2.tv_nsec = 333000;
+ timeout2.tv_sec = 0;
+ timeout3.tv_nsec = 333;
+ timeout3.tv_sec = 3;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 20;
+ IAmShTimerCallBack* buf = &testCallback.pTimer1Callback;
+ IAmShTimerCallBack* buf2 = &testCallback.pTimer2Callback;
+ IAmShTimerCallBack* buf3 = &testCallback.pTimer3Callback;
+ IAmShTimerCallBack* buf4 = &testCallback.pTimer4Callback;
+ sh_timerHandle_t handle;
+ myHandler.addTimer(timeoutTime, buf, handle, NULL);
+ myHandler.addTimer(timeout2, buf2, handle, NULL);
+ myHandler.addTimer(timeout3, buf3, handle, NULL);
+ myHandler.addTimer(timeout4, buf4, handle, NULL);
+ myHandler.start_listenting();
+
+}
+
+
TEST(CAmSocketHandlerTest,playWithUNIXSockets)
{
pthread_t serverThread;
@@ -199,32 +223,6 @@ TEST(CAmSocketHandlerTest,playWithSockets)
pthread_join(serverThread, NULL);
}
-TEST(CAmSocketHandlerTest,playWithTimers)
-{
- gDispatchDone = 0;
- CAmSocketHandler myHandler;
- CAmTimerCb testCallback(&myHandler);
- timespec timeoutTime, timeout2, timeout3, timeout4;
- timeoutTime.tv_sec = 3;
- timeoutTime.tv_nsec = 0;
- timeout2.tv_nsec = 0;
- timeout2.tv_sec = 1;
- timeout3.tv_nsec = 000000000;
- timeout3.tv_sec = 2;
- timeout4.tv_nsec = 0;
- timeout4.tv_sec = 13;
- IAmShTimerCallBack* buf = &testCallback.pTimer1Callback;
- IAmShTimerCallBack* buf2 = &testCallback.pTimer2Callback;
- IAmShTimerCallBack* buf3 = &testCallback.pTimer3Callback;
- IAmShTimerCallBack* buf4 = &testCallback.pTimer4Callback;
- sh_timerHandle_t handle;
- myHandler.addTimer(timeoutTime, buf, handle, NULL);
- myHandler.addTimer(timeout2, buf2, handle, NULL);
- myHandler.addTimer(timeout3, buf3, handle, NULL);
- myHandler.addTimer(timeout4, buf4, handle, NULL);
- myHandler.start_listenting();
-
-}
void CAmSocketHandlerTest::SetUp()
{
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0edb882..6485dcd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,9 +62,6 @@ OPTION( WITH_PLUGIN_ROUTING
OPTION( WITH_MAIN
"Build with daemon" ON)
-OPTION( WITH_PPOLL
- "libc supports ppoll" ON)
-
OPTION( WITH_TELNET
"build with Telnetserver (can only work with SocketHandler)" ON)
diff --git a/PluginControlInterface/test/CAmControlReceiverShadowTest.cpp b/PluginControlInterface/test/CAmControlReceiverShadowTest.cpp
index 3f73366..7246ff6 100644
--- a/PluginControlInterface/test/CAmControlReceiverShadowTest.cpp
+++ b/PluginControlInterface/test/CAmControlReceiverShadowTest.cpp
@@ -36,7 +36,7 @@ CAmControlReceiverShadowTest::~CAmControlReceiverShadowTest()
void CAmControlReceiverShadowTest::SetUp()
{
timespec t;
- t.tv_nsec = 10000;
+ t.tv_nsec = 1000000;
t.tv_sec = 0;
sh_timerHandle_t handle;
diff --git a/PluginRoutingInterfaceAsync/test/CAmRoutingReceiverAsync.cpp b/PluginRoutingInterfaceAsync/test/CAmRoutingReceiverAsync.cpp
index 2c13512..55e706a 100644
--- a/PluginRoutingInterfaceAsync/test/CAmRoutingReceiverAsync.cpp
+++ b/PluginRoutingInterfaceAsync/test/CAmRoutingReceiverAsync.cpp
@@ -388,12 +388,13 @@ TEST_F(CAmRoutingReceiverAsync,connectNoMoreThreads)
am_ConnectionFormat_e format = CF_GENIVI_ANALOG;
EXPECT_CALL(pReceiveInterface,ackConnect(_,_,E_OK)).Times(10);
- for (int i = 0; i < 9; i++)
+ for (int i = 0; i < 10; i++)
{
handle.handle++;
connectionID++;
ASSERT_EQ(E_OK, pRouter->asyncConnect(handle,connectionID,sourceID,sinkID,format));
- }ASSERT_EQ(E_NOT_POSSIBLE, pRouter->asyncConnect(handle,connectionID,sourceID,sinkID,format));
+ }
+ ASSERT_EQ(E_NOT_POSSIBLE, pRouter->asyncConnect(handle,connectionID,sourceID,sinkID,format));
pSocketHandler.start_listenting();
}
diff --git a/cmake/config.cmake b/cmake/config.cmake
index 8d1a8e6..c492276 100644
--- a/cmake/config.cmake
+++ b/cmake/config.cmake
@@ -5,7 +5,6 @@
#cmakedefine WITH_DBUS_WRAPPER
#cmakedefine WITH_DLT
-#cmakedefine WITH_PPOLL
#cmakedefine WITH_TELNET
#cmakedefine GLIB_DBUS_TYPES_TOLERANT
diff --git a/include/shared/CAmSerializer.h b/include/shared/CAmSerializer.h
index a88c0ad..a8c63b1 100644
--- a/include/shared/CAmSerializer.h
+++ b/include/shared/CAmSerializer.h
@@ -976,7 +976,7 @@ public:
short event = 0;
sh_pollHandle_t handle;
event |= POLLIN;
- iSocketHandler->addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, NULL, &dispatcherCallbackT, NULL, handle);
+ iSocketHandler->addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, &checkerCallbackT, &dispatcherCallbackT, NULL, handle);
}
~CAmSerializer()
diff --git a/include/shared/CAmSocketHandler.h b/include/shared/CAmSocketHandler.h
index 9c3b6e7..83d2352 100644
--- a/include/shared/CAmSocketHandler.h
+++ b/include/shared/CAmSocketHandler.h
@@ -21,7 +21,6 @@
#include "audiomanagertypes.h"
#include <sys/socket.h>
-#include <sys/time.h>
#include <stdint.h>
#include <sys/poll.h>
#include <list>
@@ -36,11 +35,55 @@ static volatile sig_atomic_t gDispatchDone = 0; //this global is used to stop th
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
-class IAmShPollPrepare;
-class IAmShPollCheck;
-class IAmShPollFired;
-class IAmShPollDispatch;
-class IAmShTimerCallBack;
+/**
+ * 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 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 the timer callback
+ */
+class IAmShTimerCallBack
+{
+public:
+ 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
@@ -72,16 +115,16 @@ private:
void * userData; //!<saves a void pointer together with the rest.
};
+ typedef std::reverse_iterator<sh_timer_s> rListTimerIter;
+
class CAmShSubstractTime //!<functor to easy substract from each countdown value
{
private:
timespec param;
public:
CAmShSubstractTime(timespec param) :
- param(param)
- {
- }
- void operator()(sh_timer_s& t) const;
+ param(param){}
+ inline void operator()(sh_timer_s& t) const;
};
struct sh_poll_s //!<struct that holds information about polls
@@ -104,88 +147,192 @@ private:
mListPollfd_t& mArray;
public:
CAmShCopyPollfd(mListPollfd_t& dest) :
- mArray(dest)
+ mArray(dest){}
+ void operator()(const sh_poll_s& row)
+ {
+ pollfd temp = row.pollfdValue;
+ temp.revents = 0;
+ mArray.push_back(temp);
+ }
+ };
+
+ class CAmShMatchingFd
+ {
+ private:
+ int mFD, mEventFlag;
+ public:
+ CAmShMatchingFd(int fd, int eventFlag) :
+ mFD(fd), //
+ mEventFlag(eventFlag)
+ { }
+ bool operator()(const sh_poll_s& a)
+ {
+ return (((a.pollfdValue.fd == mFD) && (a.pollfdValue.events == mEventFlag)) ? true : false);
+ }
+ };
+
+ class CAmShCallFire
+ {
+ public:
+ CAmShCallFire(){};
+ void operator()(sh_poll_s& row)
+ {
+ row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
+ }
+ };
+
+ class CAmShCallPrep
+ {
+ public:
+ CAmShCallPrep(){};
+ void operator()(sh_poll_s& row)
+ {
+ if (row.prepareCB)
+ row.prepareCB->Call(row.handle, row.userData);
+ }
+ };
+
+ class CAmShCallTimer
+ {
+ public:
+ CAmShCallTimer(){};
+ void operator()(sh_timer_s& row)
+ {
+ row.callback->Call(row.handle, row.userData);
+ }
+ };
+
+ class CAmShCountdownUp
+ {
+ public:
+ CAmShCountdownUp(){};
+ bool operator()(sh_timer_s& row)
+ {
+ if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
+ return (true);
+ return (false);
+ }
+ };
+
+ class CAmShCountdownSame
+ {
+ private:
+ sh_timer_s mCompareValue;
+ public:
+ CAmShCountdownSame(sh_timer_s& a) :
+ mCompareValue(a)
+ {}
+ bool operator()(const sh_timer_s& b)
{
+ return ((mCompareValue.countdown.tv_sec == b.countdown.tv_sec) && (mCompareValue.countdown.tv_nsec == b.countdown.tv_nsec) ? true : false);
}
- void operator()(const sh_poll_s& row);
};
bool fdIsValid(const int fd) const;
void initTimer();
void timerUp();
+ void timerCorrection();
int timespec2ms(const timespec& time);
timespec* insertTime(timespec& buffertime);
+
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));
}
- static bool onlyFiredEvents(const pollfd& a)
+ /**
+ * Subtracts b from a
+ * @param a
+ * @param b
+ * @return subtracted value
+ */
+ 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 + 1000000000L - b.tv_nsec;
+ result.tv_sec--; /* Borrow a second. */
+ }
+ else
+ {
+ result.tv_nsec = a.tv_nsec - b.tv_nsec;
+ }
+ }
+ return (result);
+ }
+
+ static 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 >= 1000000000L)
+ {
+ result.tv_sec++;
+ result.tv_nsec = result.tv_nsec - 1000000000L;
+ }
+ return (result);
+ }
+
+ static 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
+ else
+ return (0);
+ }
+
+ inline static bool eventFired(const pollfd& a)
{
return (a.revents == 0 ? false : true);
}
- //todo: maybe we could simplify mListActiveTimer to hold only the handle and the countdown ....
+ 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));
+ }
+
+ 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));
+ }
+
mListPollfd_t mfdPollingArray;
mListPoll_t mListPoll;
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 mNextTimer;
sh_timerHandle_t mLastInsertedHandle;
sh_pollHandle_t mLastInsertedPollHandle;
bool mRecreatePollfds;
- timespec mTimeout;
-};
-
-/**
- * prototype for the timer callback
- */
-class IAmShTimerCallBack
-{
-public:
- virtual void Call(const sh_timerHandle_t handle, void* userData)=0;
- virtual ~IAmShTimerCallBack(){};
-};
-
-/**
- * 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 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(){};
-};
+ timespec mStartTime;
+}
+;
/**
* template to create the functor for a class
@@ -224,8 +371,7 @@ public:
virtual void Call(const sh_timerHandle_t handle, void* userData)
{
(*mInstance.*mFunction)(handle, userData);
- }
- ;
+ };
};
/**
@@ -245,8 +391,7 @@ public:
virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
{
(*mInstance.*mFunction)(pollfd, handle, userData);
- }
- ;
+ };
};
/**
@@ -266,8 +411,7 @@ public:
virtual bool Call(const sh_pollHandle_t handle, void* userData)
{
return ((*mInstance.*mFunction)(handle, userData));
- }
- ;
+ };
};
/**
@@ -287,8 +431,7 @@ public:
virtual bool Call(const sh_pollHandle_t handle, void* userData)
{
return ((*mInstance.*mFunction)(handle, userData));
- }
- ;
+ };
};
} /* namespace am */
#endif /* SOCKETHANDLER_H_ */