26 #include <sys/fcntl.h> 27 #include <sys/errno.h> 39 #include <sys/timerfd.h> 55 mRecreatePollfds(true),
56 mInternalCodes(internal_codes_e::NO_ERROR),
62 if (pipe(mPipe) == -1)
64 mInternalCodes = internal_codes_e::PIPE_ERROR;
65 logError(
"Sockethandler could not create pipe!");
75 NULL, NULL, handle) !=
E_OK)
77 mInternalCodes |= internal_codes_e::FD_ERROR;
83 for (
auto it : mListPoll)
85 close(it.pollfdValue.fd);
97 mDispatchDone =
false;
101 clock_gettime(CLOCK_MONOTONIC, &mStartTime);
105 VectorListPoll_t cloneListPoll;
106 VectorListPoll_t::iterator listmPollIt;
107 VectorListPollfd_t fdPollingArray;
109 auto preparePollfd = [&](
const sh_poll_s& row)
111 CAmSocketHandler::prepare((sh_poll_s&)row);
112 pollfd temp = row.pollfdValue;
114 fdPollingArray.push_back(temp);
117 while (!mDispatchDone)
119 if (mRecreatePollfds)
121 fdPollingArray.clear();
123 cloneListPoll = mListPoll;
125 std::for_each(cloneListPoll.begin(), cloneListPoll.end(), preparePollfd);
126 mRecreatePollfds =
false;
131 std::for_each(cloneListPoll.begin(), cloneListPoll.end(), CAmSocketHandler::prepare);
139 if ((pollStatus = ppoll(&fdPollingArray[0], fdPollingArray.size(), insertTime(buffertime), NULL)) < 0)
148 logError(
"SocketHandler::start_listenting ppoll returned with error", errno);
149 throw std::runtime_error(std::string(
"SocketHandler::start_listenting ppoll returned with error."));
155 std::list<sh_poll_s> listPoll;
158 listmPollIt = cloneListPoll.begin();
159 for (
auto it : fdPollingArray)
161 if (CAmSocketHandler::eventFired(it))
163 listmPollIt->pollfdValue.revents = it.revents;
164 listPoll.push_back(*listmPollIt);
165 CAmSocketHandler::fire(*listmPollIt);
169 listmPollIt->pollfdValue.revents = 0;
175 listPoll.remove_if(CAmSocketHandler::noDispatching);
180 listPoll.remove_if(CAmSocketHandler::dispatchingFinished);
181 }
while (!listPoll.empty());
200 mDispatchDone =
true;
203 if (!mListActiveTimer.empty())
205 timespec currentTime, correctionTime;
206 clock_gettime(CLOCK_MONOTONIC, ¤tTime);
207 correctionTime = timespecSub(currentTime, mStartTime);
208 std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), [&correctionTime](sh_timer_s& t)
209 { t.countdown = timespecSub(t.countdown, correctionTime);});
221 ssize_t result = write(mPipe[1], &p,
sizeof(p));
226 return ((mInternalCodes&internal_codes_e::PIPE_ERROR)>0)||((mInternalCodes&internal_codes_e::FD_ERROR)>0);
231 VectorListPoll_t::iterator iterator = mListPoll.begin();
232 for (; iterator != mListPoll.end(); ++iterator)
234 if (iterator->handle == handle)
236 outPollData = *iterator;
250 uint8_t addedSignals = 0;
253 if(0==listSignals.size())
260 fdErr = sigemptyset(&sigset);
263 logError(
"Could not create sigset!");
267 for(uint8_t itSignal : listSignals)
269 fdErr = sigaddset(&sigset, itSignal);
278 logWarning(
"None of the signals were added!");
283 fdErr = sigprocmask(SIG_BLOCK, &sigset, NULL);
286 logError(
"Could not block signals! They must be blocked in order to receive them!");
293 sh_poll_s sgPollData;
294 if(
E_OK!=getFDPollData(mSignalFdHandle, sgPollData))
301 int signalHandlerFd = signalfd(sgPollData.pollfdValue.fd, &sigset, 0);
302 if (signalHandlerFd == -1)
304 logError(
"Could not update signal fd!");
311 if(0==mSignalFdHandle)
314 signalHandlerFd = signalfd(-1, &sigset, 0);
315 if (signalHandlerFd == -1)
317 logError(
"Could not open signal fd!");
321 auto actionPoll = [
this](
const pollfd pollfd,
const sh_pollHandle_t,
void*)
323 const VectorSignalHandlers_t & signalHandlers = mSignalHandlers;
325 struct signalfd_siginfo info;
326 ssize_t bytes = read(pollfd.fd, &info,
sizeof(info));
327 assert(bytes ==
sizeof(info));
330 for(
auto it: signalHandlers)
331 it.callback(it.handle, info, it.userData);
334 am_Error_e shFdError =
addFDPoll(signalHandlerFd, POLLIN | POLLERR | POLLHUP, NULL, actionPoll, [](
const sh_pollHandle_t,
void*)
335 {
return (
false);}, NULL, NULL, mSignalFdHandle);
354 std::function<
void(
const pollfd pollfd,
const sh_pollHandle_t handle,
void* userData)> fired, std::function<
bool(
const sh_pollHandle_t handle,
void* userData)> check,
361 if (!nextHandle(mSetPollKeys))
363 logError(
"Could not create new polls, too many open!");
368 pollData.pollfdValue.fd = fd;
369 pollData.handle = mSetPollKeys.lastUsedID;
370 pollData.pollfdValue.events = event;
371 pollData.pollfdValue.revents = 0;
372 pollData.prepareCB = prepare;
373 pollData.firedCB = fired;
374 pollData.checkCB = check;
375 pollData.dispatchCB = dispatch;
376 pollData.userData = userData;
378 mListPoll.push_back(pollData);
380 mRecreatePollfds =
true;
382 handle = pollData.handle;
402 std::function<void(const sh_pollHandle_t handle, void* userData)> prepareCB;
403 std::function<void(const pollfd poll, const sh_pollHandle_t handle, void* userData)> firedCB;
404 std::function<bool(const sh_pollHandle_t handle, void* userData)> checkCB;
405 std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatchCB;
410 firedCB = std::bind(&
IAmShPollFired::Call, fired, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
412 checkCB = std::bind(&
IAmShPollCheck::Call, check, std::placeholders::_1, std::placeholders::_2);
416 return addFDPoll(fd, event, prepareCB, firedCB, checkCB, dispatchCB, userData, handle);
426 VectorListPoll_t::iterator iterator = mListPoll.begin();
428 for (; iterator != mListPoll.end(); ++iterator)
430 if (iterator->handle == handle)
432 iterator = mListPoll.erase(iterator);
433 mSetPollKeys.pollHandles.erase(handle);
434 mRecreatePollfds =
true;
450 if (!nextHandle(mSetSignalhandlerKeys))
452 logError(
"Could not create new polls, too many open!");
456 mSignalHandlers.emplace_back();
457 mSignalHandlers.back().callback = callback;
458 mSignalHandlers.back().handle = mSetSignalhandlerKeys.lastUsedID;
459 mSignalHandlers.back().userData = userData;
460 handle = mSetSignalhandlerKeys.lastUsedID;
472 VectorSignalHandlers_t::iterator it(mSignalHandlers.begin());
473 for (; it != mSignalHandlers.end(); ++it)
475 if (it->handle == handle)
477 it = mSignalHandlers.erase(it);
478 mSetSignalhandlerKeys.pollHandles.erase(handle);
499 assert(callback!=NULL);
501 std::function<void(const sh_timerHandle_t handle, void* userData)> callbackFunc;
504 return addTimer(timeouts, callbackFunc, handle, userData, repeats);
509 assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0)));
511 mListTimer.emplace_back();
512 sh_timer_s & timerItem = mListTimer.back();
516 if (!nextHandle(mSetTimerKeys))
518 logError(
"Could not create new timers, too many open!");
519 mListTimer.pop_back();
523 handle = mSetTimerKeys.lastUsedID;
525 timerItem.countdown = timeouts;
526 timerItem.callback = callback;
527 timerItem.userData = userData;
529 timerItem.handle = handle;
532 timespec currentTime;
533 clock_gettime(CLOCK_MONOTONIC, ¤tTime);
535 timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
536 mListTimer.push_back(timerItem);
537 mListActiveTimer.push_back(timerItem);
538 mListActiveTimer.sort(compareCountdown);
542 timerItem.countdown.it_value = timeouts;
544 timerItem.countdown.it_interval = timeouts;
550 timerItem.countdown.it_interval = zero;
554 timerItem.userData = userData;
555 am_Error_e err = createTimeFD(timerItem.countdown, timerItem.fd);
558 mListTimer.pop_back();
562 static auto actionPoll = [](
const pollfd pollfd,
const sh_pollHandle_t handle,
void* userData)
564 uint64_t mExpirations;
565 if (read(pollfd.fd, &mExpirations,
sizeof(uint64_t)) == -1)
568 read(pollfd.fd, &mExpirations,
sizeof(uint64_t));
572 err =
addFDPoll(timerItem.fd, POLLIN, NULL, actionPoll, [callback](
const sh_pollHandle_t handle,
void* userData)->bool
574 callback(handle, userData);
577 NULL, userData, handle);
580 timerItem.handle = handle;
584 mListTimer.pop_back();
602 std::list<sh_timer_s>::iterator it = mListTimer.begin();
603 for (; it != mListTimer.end(); ++it)
605 if (it->handle == handle)
608 if (it == mListTimer.end())
612 mListTimer.erase(it);
616 std::list<sh_timer_s>::iterator it(mListTimer.begin());
617 for (; it != mListTimer.end(); ++it)
619 if (it->handle == handle)
621 it = mListTimer.erase(it);
622 mSetTimerKeys.pollHandles.erase(handle);
639 std::list<sh_timer_s>::iterator it = mListTimer.begin();
640 for (; it != mListTimer.end(); ++it)
642 if (it->handle == handle)
645 if (it == mListTimer.end())
648 if (it->countdown.it_interval.tv_nsec != 0 || it->countdown.it_interval.tv_sec != 0)
649 it->countdown.it_interval = timeouts;
650 it->countdown.it_value = timeouts;
652 if (!fdIsValid(it->fd))
654 am_Error_e err = createTimeFD(it->countdown, it->fd);
660 if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
662 logError(
"Failed to set timer duration");
669 sh_timer_s timerItem;
670 std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
672 for (; it != mListTimer.end(); ++it)
674 if (it->handle == handle)
676 it->countdown = timeouts;
688 timespec currentTime, timeoutsCorrected;
689 currentTime.tv_nsec=timeoutsCorrected.tv_nsec=0;
690 currentTime.tv_sec=timeoutsCorrected.tv_sec=0;
691 clock_gettime(CLOCK_MONOTONIC, ¤tTime);
693 timeoutsCorrected = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
695 for (; activeIt != mListActiveTimer.end(); ++activeIt)
697 if (activeIt->handle == handle)
699 activeIt->countdown = timeoutsCorrected;
706 timerItem.countdown = timeoutsCorrected;
707 mListActiveTimer.push_back(timerItem);
709 mListActiveTimer.sort(compareCountdown);
723 std::list<sh_timer_s>::iterator it = mListTimer.begin();
724 for (; it != mListTimer.end(); ++it)
726 if (it->handle == handle)
729 if (it == mListTimer.end())
732 if (!fdIsValid(it->fd))
734 am_Error_e err = createTimeFD(it->countdown, it->fd);
740 if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
742 logError(
"Failed to set timer duration");
748 sh_timer_s timerItem;
750 std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
752 for (; it != mListTimer.end(); ++it)
754 if (it->handle == handle)
767 timespec currentTime, timeoutsCorrected;
768 clock_gettime(CLOCK_MONOTONIC, ¤tTime);
771 timeoutsCorrected = timespecAdd(timerItem.countdown, timespecSub(currentTime, mStartTime));
772 timerItem.countdown = timeoutsCorrected;
775 for (; activeIt != mListActiveTimer.end(); ++activeIt)
777 if (activeIt->handle == handle)
779 activeIt->countdown = timerItem.countdown;
786 mListActiveTimer.push_back(timerItem);
788 mListActiveTimer.sort(compareCountdown);
801 std::list<sh_timer_s>::iterator it = mListTimer.begin();
802 for (; it != mListTimer.end(); ++it)
804 if (it->handle == handle)
807 if (it == mListTimer.end())
810 itimerspec countdown = it->countdown;
811 countdown.it_value.tv_nsec = 0;
812 countdown.it_value.tv_sec = 0;
814 if (timerfd_settime(it->fd, 0, &countdown, NULL))
816 logError(
"Failed to set timer duration");
822 std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
823 for (; it != mListActiveTimer.end(); ++it)
825 if (it->handle == handle)
827 it = mListActiveTimer.erase(it);
843 VectorListPoll_t::iterator iterator = mListPoll.begin();
845 for (; iterator != mListPoll.end(); ++iterator)
847 if (iterator->handle == handle)
849 iterator->pollfdValue.events = events;
850 mRecreatePollfds =
true;
862 bool CAmSocketHandler::fdIsValid(
const int fd)
const 864 return (fcntl(fd, F_GETFL) != -1 || errno != EBADF);
871 void CAmSocketHandler::timerUp()
874 static timespec currentTime, diffTime;
875 clock_gettime(CLOCK_MONOTONIC, ¤tTime);
876 diffTime = timespecSub(currentTime, mStartTime);
878 static auto countdownUp = [&](
const sh_timer_s& row)->
bool 880 timespec sub = timespecSub(row.countdown, diffTime);
881 if (sub.tv_nsec == 0 && sub.tv_sec == 0)
887 std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownUp);
890 std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
893 std::list<sh_timer_s>::iterator it(overflowIter.base());
894 mListActiveTimer.erase(mListActiveTimer.begin(), it);
897 std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
903 void CAmSocketHandler::timerCorrection()
906 static timespec currentTime, correctionTime;
907 clock_gettime(CLOCK_MONOTONIC, ¤tTime);
908 correctionTime = timespecSub(currentTime, mStartTime);
909 mStartTime = currentTime;
911 static auto countdownZero = [](
const sh_timer_s& row)->
bool 913 if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
918 static auto substractTime = [&](sh_timer_s& t)
920 t.countdown = timespecSub(t.countdown, correctionTime);
923 if (!mListActiveTimer.empty())
927 std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), substractTime);
930 std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownZero);
933 if (overflowIter != mListActiveTimer.rend())
936 std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
939 std::list<sh_timer_s>::iterator it(overflowIter.base());
940 mListActiveTimer.erase(mListActiveTimer.begin(), it);
943 std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
952 void CAmSocketHandler::prepare(am::CAmSocketHandler::sh_poll_s& row)
958 row.prepareCB(row.handle, row.userData);
959 }
catch (std::exception& e)
961 logError(
"Sockethandler: Exception in Preparecallback,caught", e.what());
969 void CAmSocketHandler::fire(sh_poll_s& a)
973 a.firedCB(a.pollfdValue, a.handle, a.userData);
974 }
catch (std::exception& e)
976 logError(
"Sockethandler: Exception in Preparecallback,caught", e.what());
983 bool CAmSocketHandler::noDispatching(
const sh_poll_s& a)
986 if (
nullptr == a.checkCB)
988 return (!a.checkCB(a.handle, a.userData));
994 bool CAmSocketHandler::dispatchingFinished(
const sh_poll_s& a)
997 if (
nullptr == a.dispatchCB)
999 return (!a.dispatchCB(a.handle, a.userData));
1005 bool CAmSocketHandler::eventFired(
const pollfd& a)
1007 return (a.revents == 0 ?
false :
true);
1015 inline timespec* CAmSocketHandler::insertTime(timespec& buffertime)
1017 #ifndef WITH_TIMERFD 1018 if (!mListActiveTimer.empty())
1020 buffertime = mListActiveTimer.front().countdown;
1021 return (&buffertime);
1031 am_Error_e CAmSocketHandler::createTimeFD(
const itimerspec & timeouts,
int & fd)
1033 fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
1036 logError(
"Failed to create timer");
1040 if (timerfd_settime(fd, 0, &timeouts, NULL))
1042 logError(
"Failed to set timer duration");
1049 void CAmSocketHandler::callTimer(sh_timer_s& a)
1053 a.callback(a.handle, a.userData);
1054 }
catch (std::exception& e)
1056 logError(
"Sockethandler: Exception in Timercallback,caught", e.what());
1060 bool CAmSocketHandler::nextHandle(sh_identifier_s & handle)
1066 ++handle.lastUsedID;
1067 if (handle.lastUsedID == handle.limit)
1069 handle.lastUsedID = 1;
1071 if (handle.lastUsedID == lastHandle)
1073 logError(
"Could not create new polls, too many open!");
1077 }
while (handle.pollHandles.find(handle.lastUsedID) != handle.pollHandles.end());
1079 handle.pollHandles.insert(handle.lastUsedID);
void logWarning(T value, TArgs...args)
logs given values with warninglevel with the default context
A Common-API wrapper class, which loads the common-api runtime and instantiates all necessary objects...
the desired object is non existent
am_Error_e
the errors of the audiomanager.
virtual bool Call(const sh_pollHandle_t handle, void *userData)=0
prototype for poll fired callback
am_Error_e restartTimer(const sh_timerHandle_t handle)
restarts a timer with the original value
virtual bool Call(const sh_pollHandle_t handle, void *userData)=0
uint16_t sh_pollHandle_t
this is a handle for a filedescriptor to be used with the SocketHandler
SPDX license identifier: MPL-2.0.
prototype for poll check callback
am_Error_e removeFDPoll(const sh_pollHandle_t handle)
removes a filedescriptor from the poll loop
prototype for poll prepared callback
am_Error_e removeTimer(const sh_timerHandle_t handle)
removes a timer from the list of timers
am_Error_e stopTimer(const sh_timerHandle_t handle)
stops a timer
virtual void Call(const sh_pollHandle_t handle, void *userData)=0
am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec &timeouts)
restarts a timer and updates with a new interva
am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events)
updates the eventFlags of a poll
void start_listenting()
start the block listening for filedescriptors.
am_Error_e listenToSignals(const std::vector< uint8_t > &listSignals)
install the signal fd
prototype for dispatch callback
virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void *userData)=0
the desired action is not possible
am_Error_e addFDPoll(const int fd, const short event, std::function< void(const sh_pollHandle_t handle, void *userData)> prepare, std::function< void(const pollfd pollfd, const sh_pollHandle_t handle, void *userData)> fired, std::function< bool(const sh_pollHandle_t handle, void *userData)> check, std::function< bool(const sh_pollHandle_t handle, void *userData)> dispatch, void *userData, sh_pollHandle_t &handle)
Adds a filedescriptor to the polling loop.
SPDX license identifier: MPL-2.0.
void logError(T value, TArgs...args)
logs given values with errorlevel with the default context
prototype for the timer callback
am_Error_e addSignalHandler(std::function< void(const sh_pollHandle_t handle, const signalfd_siginfo &info, void *userData)> callback, sh_pollHandle_t &handle, void *userData)
Adds a callback for any signals.
am_Error_e removeSignalHandler(const sh_pollHandle_t handle)
removes a signal handler from the list
no error - positive reply
virtual void Call(const sh_timerHandle_t handle, void *userData)=0
sh_pollHandle_t sh_timerHandle_t
this is a handle for a timer to be used with the SocketHandler
void stop_listening()
exits the loop
am_Error_e addTimer(const timespec &timeouts, IAmShTimerCallBack *callback, sh_timerHandle_t &handle, void *userData, const bool __attribute__((__unused__)) repeats=false)
bool fatalErrorOccurred()