42 #include "qplatformdefs.h" 51 #include <private/qthread_p.h> 52 #include <private/qcoreapplication_p.h> 53 #include <private/qcore_unix_p.h> 60 #if defined(Q_OS_VXWORKS) 61 # if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0) 62 # undef _POSIX_MONOTONIC_CLOCK 63 # define _POSIX_MONOTONIC_CLOCK 1 66 # include <selectLib.h> 69 #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) 70 # include <sys/times.h> 91 #if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS) 92 static void initThreadPipeFD(
int fd)
94 int ret =
fcntl(fd, F_SETFD, FD_CLOEXEC);
96 perror(
"QEventDispatcherUNIXPrivate: Unable to init thread pipe");
98 int flags =
fcntl(fd, F_GETFL);
100 perror(
"QEventDispatcherUNIXPrivate: Unable to get flags on thread pipe");
102 ret =
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
104 perror(
"QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe");
112 bool pipefail =
false;
115 #if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY) 117 #elif defined(Q_OS_INTEGRITY) 119 if (socketpair(AF_INET, SOCK_STREAM, 0,
thread_pipe) == -1) {
120 perror(
"QEventDispatcherUNIXPrivate(): Unable to create socket pair");
126 #elif defined(Q_OS_VXWORKS) 128 qsnprintf(name,
sizeof(name),
"/pipe/qt_%08x",
int(taskIdSelf()));
131 pipeDevDelete(name,
true);
133 if (pipeDevCreate(name, 128 , 1 ) != OK) {
134 perror(
"QEventDispatcherUNIXPrivate(): Unable to create thread pipe device");
138 perror(
"QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
147 perror(
"QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
153 qFatal(
"QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
162 #if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY) 164 #elif defined(Q_OS_VXWORKS) 168 qsnprintf(name,
sizeof(name),
"/pipe/qt_%08x",
int(taskIdSelf()));
170 pipeDevDelete(name,
true);
193 for (
int i = 0; i < NSIG; ++i) {
211 FD_ZERO(&
sn_vec[0].select_fds);
212 FD_ZERO(&
sn_vec[1].select_fds);
213 FD_ZERO(&
sn_vec[2].select_fds);
217 highest =
qMax(highest, wakeUpFd);
219 nsel = q->select(highest + 1,
224 }
while (nsel == -1 && (
errno == EINTR ||
errno == EAGAIN));
227 if (
errno == EBADF) {
232 tm.tv_sec = tm.tv_usec = 0
l;
236 if (list.
size() == 0)
239 for (
int i = 0; i < list.
size(); ++i) {
243 FD_SET(sn->
fd, &fdset);
249 ret =
select(sn->
fd + 1, &fdset, 0, 0, &tm);
252 ret =
select(sn->
fd + 1, 0, &fdset, 0, &tm);
255 ret =
select(sn->
fd + 1, 0, 0, &fdset, &tm);
258 }
while (ret == -1 && (
errno == EINTR ||
errno == EAGAIN));
260 if (ret == -1 &&
errno == EBADF) {
262 static const char *t[] = {
"Read",
"Write",
"Exception" };
263 qWarning(
"QSocketNotifier: Invalid socket %d and type '%s', disabling...",
282 for (
int i=0; i<3; i++) {
284 for (
int j = 0; j < list.
size(); ++j) {
287 q->setSocketNotifierPending(sn->
obj);
291 return (nevents + q->activateSocketNotifiers());
305 #if defined(Q_OS_VXWORKS) 316 qWarning(
"QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!");
330 #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL) 336 previousTicks = times(&unused);
338 ticksPerSecond = sysconf(_SC_CLK_TCK);
339 msPerTick = 1000/ticksPerSecond;
342 previousTime.tv_sec = previousTime.tv_usec = 0;
357 #if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_INTEGRITY)) || defined(QT_BOOTSTRAPPED) 359 timeval qAbsTimeval(
const timeval &t)
362 if (tmp.tv_sec < 0) {
363 tmp.tv_sec = -tmp.tv_sec - 1;
364 tmp.tv_usec -= 1000000;
366 if (tmp.tv_sec == 0 && tmp.tv_usec < 0) {
367 tmp.tv_usec = -tmp.tv_usec;
379 bool QTimerInfoList::timeChanged(timeval *delta)
386 clock_t currentTicks = times(&unused);
388 clock_t elapsedTicks = currentTicks - previousTicks;
389 timeval elapsedTime = currentTime - previousTime;
391 timeval elapsedTimeTicks;
392 elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond;
393 elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000;
398 *delta = elapsedTime - elapsedTimeTicks;
400 previousTicks = currentTicks;
401 previousTime = currentTime;
405 timeval tickGranularity;
406 tickGranularity.tv_sec = 0;
407 tickGranularity.tv_usec = msPerTick * 1000;
408 return elapsedTimeTicks < ((qAbsTimeval(*delta) - tickGranularity) * 10);
416 if (timeChanged(&delta))
420 #else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED) 448 for (
int i = 0; i < size(); ++i) {
460 timeval currentTime = updateCurrentTime();
461 repairTimersIfNeeded();
466 if (!(*it)->activateRef) {
475 if (currentTime < t->timeout) {
491 t->
interval.tv_sec = interval / 1000;
492 t->
interval.tv_usec = (interval % 1000) * 1000;
503 for (
int i = 0; i < count(); ++i) {
505 if (t->
id == timerId) {
508 if (t == firstTimerInfo)
529 for (
int i = 0; i < count(); ++i) {
531 if (t->
obj ==
object) {
534 if (t == firstTimerInfo)
554 for (
int i = 0; i < count(); ++i) {
556 if (t->
obj ==
object)
557 list << QPair<int, int>(t->
id, t->
interval.tv_sec * 1000 + t->
interval.tv_usec / 1000);
570 int n_act = 0, maxCount = 0;
573 timeval currentTime = updateCurrentTime();
574 repairTimersIfNeeded();
579 if (currentTime < (*it)->timeout)
590 if (currentTime < currentTimerInfo->timeout)
593 if (!firstTimerInfo) {
594 firstTimerInfo = currentTimerInfo;
595 }
else if (firstTimerInfo == currentTimerInfo) {
598 }
else if (currentTimerInfo->
interval < firstTimerInfo->interval
599 || currentTimerInfo->
interval == firstTimerInfo->interval) {
600 firstTimerInfo = currentTimerInfo;
608 if (currentTimerInfo->
timeout < currentTime)
612 timerInsert(currentTimerInfo);
613 if (currentTimerInfo->
interval.tv_usec > 0 || currentTimerInfo->
interval.tv_sec > 0)
623 if (currentTimerInfo)
643 d->threadData->eventDispatcher = 0;
649 return qt_safe_select(nfds, readfds, writefds, exceptfds, timeout);
658 if (timerId < 1 || interval < 0 || !obj) {
659 qWarning(
"QEventDispatcherUNIX::registerTimer: invalid arguments");
662 qWarning(
"QObject::startTimer: timers cannot be started from another thread");
668 d->timerList.registerTimer(timerId, interval, obj);
678 qWarning(
"QEventDispatcherUNIX::unregisterTimer: invalid argument");
681 qWarning(
"QObject::killTimer: timers cannot be stopped from another thread");
687 return d->timerList.unregisterTimer(timerId);
697 qWarning(
"QEventDispatcherUNIX::unregisterTimers: invalid argument");
700 qWarning(
"QObject::killTimers: timers cannot be stopped from another thread");
706 return d->timerList.unregisterTimers(
object);
713 qWarning(
"QEventDispatcherUNIX:registeredTimers: invalid argument");
718 return d->timerList.registeredTimers(
object);
726 FD_ZERO(&select_fds);
727 FD_ZERO(&enabled_fds);
728 FD_ZERO(&pending_fds);
733 for (
int i = 0; i < list.size(); ++i)
744 int sockfd = notifier->
socket();
748 ||
unsigned(sockfd) >= FD_SETSIZE) {
749 qWarning(
"QSocketNotifier: Internal error");
753 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
760 fd_set *fds = &
d->sn_vec[
type].enabled_fds;
769 for (i = 0; i < list.
size(); ++i) {
773 if (p->
fd == sockfd) {
774 static const char *t[] = {
"Read",
"Write",
"Exception" };
775 qWarning(
"QSocketNotifier: Multiple socket notifiers for " 776 "same socket %d and type %s", sockfd, t[type]);
782 d->sn_highest =
qMax(
d->sn_highest, sockfd);
788 int sockfd = notifier->
socket();
792 ||
unsigned(sockfd) >= FD_SETSIZE) {
793 qWarning(
"QSocketNotifier: Internal error");
797 qWarning(
"QSocketNotifier: socket notifiers cannot be disabled from another thread");
804 fd_set *fds = &
d->sn_vec[
type].enabled_fds;
807 for (i = 0; i < list.
size(); ++i) {
809 if(sn->
obj == notifier && sn->
fd == sockfd)
812 if (i == list.
size())
816 FD_CLR(sockfd, sn->
queue);
817 d->sn_pending_list.removeAll(sn);
821 if (
d->sn_highest == sockfd) {
823 for (
int i=0; i<3; i++) {
824 if (!
d->sn_vec[i].list.isEmpty())
825 d->sn_highest =
qMax(
d->sn_highest,
826 d->sn_vec[i].list[0]->fd);
834 int sockfd = notifier->
socket();
838 ||
unsigned(sockfd) >= FD_SETSIZE) {
839 qWarning(
"QSocketNotifier: Internal error");
849 for (i = 0; i < list.
size(); ++i) {
851 if(sn->
obj == notifier && sn->
fd == sockfd)
854 if (i == list.
size())
863 if (! FD_ISSET(sn->
fd, sn->
queue)) {
864 if (
d->sn_pending_list.isEmpty()) {
865 d->sn_pending_list.append(sn);
867 d->sn_pending_list.insert((
qrand() & 0xff) %
868 (
d->sn_pending_list.size()+1), sn);
878 return d->timerList.activateTimers();
884 if (
d->sn_pending_list.isEmpty())
890 while (!
d->sn_pending_list.isEmpty()) {
891 QSockNot *sn =
d->sn_pending_list.takeFirst();
892 if (FD_ISSET(sn->
fd, sn->
queue)) {
904 d->interrupt =
false;
911 const bool canWait = (
d->threadData->canWaitLocked()
921 timeval wait_tm = { 0
l, 0
l };
923 if (
d->timerList.timerWait(wait_tm))
936 nevents =
d->doSelect(flags, tm);
939 if (! (flags & QEventLoop::X11ExcludeTimers)) {
944 return (nevents > 0);
956 if (
d->wakeUps.testAndSetAcquire(0, 1)) {
979 sigemptyset(&(sa.sa_mask));
984 sa.sa_handler = SIG_DFL;
static sig_atomic_t signal_received
bool unregisterTimer(int timerId)
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
void setSocketNotifierPending(QSocketNotifier *notifier)
void flush()
Flushes the event queue.
#define QT_END_NAMESPACE
This macro expands to.
QList< TimerInfo > registeredTimers(QObject *object) const
Returns a list of registered timers for object.
#define it(className, varName)
int doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout)
timeval updateCurrentTime()
void timerInsert(QTimerInfo *)
bool hasPendingEvents()
Returns true if there is an event waiting; otherwise returns false.
#define at(className, varName)
QEventDispatcherUNIXPrivate()
~QEventDispatcherUNIXPrivate()
int select(int, fd_set *, fd_set *, fd_set *, struct timeval *)
void registerTimer(int timerId, int interval, QObject *object)
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt,...)
Q_CORE_EXPORT int qrand()
The QObject class is the base class of all Qt objects.
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
static QObjectPrivate * get(QObject *o)
void unixSignal(int)
This signal is emitted whenever a Unix signal is received by the application.
int activateSocketNotifiers()
static bool isMonotonic()
Returns true if this is a monotonic clock, false otherwise.
bool testAndSetRelease(int expectedValue, int newValue)
Atomic test-and-set.
Type type() const
Returns the socket event type specified to the constructor.
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
void registerSocketNotifier(QSocketNotifier *notifier)
Registers notifier with the event loop.
Q_CORE_EXPORT bool qt_disable_lowpriority_timers
void timerRepair(const timeval &)
friend class const_iterator
QTimerInfo ** activateRef
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
QList< QPair< int, int > > registeredTimers(QObject *object) const
bool unregisterTimer(int timerId)
#define QT_BEGIN_NAMESPACE
This macro expands to.
void awake()
This signal is emitted after the event loop returns from a function that could block.
static bool isEmpty(const char *str)
static sig_atomic_t signals_fired[NSIG]
static void watchUnixSignal(int signal, bool watch)
timeval & normalizedTimeval(timeval &t)
bool unregisterTimers(QObject *object)
Q_CORE_EXPORT void qWarning(const char *,...)
static int qt_safe_pipe(int pipefd[2], int flags=0)
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
void interrupt()
Interrupts event dispatching; i.
virtual int initThreadWakeUp()
void wakeUp()
Wakes up the event loop.
Q_CORE_EXPORT void qFatal(const char *,...)
void aboutToBlock()
This signal is emitted before the event loop calls a function that could block.
bool unregisterTimers(QObject *object)
void repairTimersIfNeeded()
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *orig_timeout)
The QTimerEvent class contains parameters that describe a timer event.
static QCoreApplication * instance()
Returns a pointer to the application's QCoreApplication (or QApplication) instance.
int sigaction(int, const struct sigaction *, struct sigaction *)
QObject * parent() const
Returns a pointer to the parent object.
void insert(int idx, const T &t)
bool processEvents(QEventLoop::ProcessEventsFlags flags)
Processes pending events that match flags until there are no more events to process.
void setEnabled(bool)
If enable is true, the notifier is enabled; otherwise the notifier is disabled.
static void releaseTimerId(int id)
virtual int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout)
void registerTimer(int timerId, int interval, QObject *object)
bool timerWait(timeval &)
QThread * thread() const
Returns the thread in which the object lives.
virtual int processThreadWakeUp(int nsel)
QEventDispatcherUNIX(QObject *parent=0)
The QEvent class is the base class of all event classes.
static void signalHandler(int sig)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
void unregisterSocketNotifier(QSocketNotifier *notifier)
Unregisters notifier from the event dispatcher.
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
Qt::HANDLE qt_application_thread_id
int open(const char *, int,...)
static qint64 qt_safe_write(int fd, const void *data, qint64 len)
int socket() const
Returns the socket identifier specified to the constructor.
The QList class is a template class that provides lists.
static Qt::HANDLE currentThreadId()
Returns the thread handle of the currently executing thread.