From f2f42846720bcb6278e30d9234e911152507de8b Mon Sep 17 00:00:00 2001 From: christian mueller Date: Fri, 23 Mar 2012 13:43:37 +0100 Subject: * [GAM-46] improvements on CAmSockthandler. * Needed adoptions on CAmSockethandler tests * Small bug in CAmSerializer Signed-off-by: christian mueller --- AudioManagerDaemon/src/CAmSocketHandler.cpp | 244 +++++++---------- .../AmSocketHandlerTest/CAmSocketHandlerTest.cpp | 68 +++-- CMakeLists.txt | 3 - .../test/CAmControlReceiverShadowTest.cpp | 2 +- .../test/CAmRoutingReceiverAsync.cpp | 5 +- cmake/config.cmake | 1 - include/shared/CAmSerializer.h | 2 +- include/shared/CAmSocketHandler.h | 293 +++++++++++++++------ 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 #include #include -#include #include +#include #include #include #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 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 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::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::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::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 tempList(overflowIter, mListActiveTimer.rend()); + + //erase all fired timers + std::list::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, ¤tTime); + 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::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 tempList(overflowIter, mListActiveTimer.rend()); + + //erase all fired timers + std::list::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 -#include #include #include #include @@ -36,11 +35,55 @@ static volatile sig_atomic_t gDispatchDone = 0; //this global is used to stop th typedef uint16_t sh_timerHandle_t; //! rListTimerIter; + class CAmShSubstractTime //!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 mListTimer; //! mListActiveTimer; //!