summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp161
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h30
2 files changed, 111 insertions, 80 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index 7fd18dc9c1..1faeb7dc39 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -95,6 +95,28 @@ static pollfd make_pollfd(int fd, short events)
return pfd;
}
+QThreadPipe::QThreadPipe()
+{
+ fds[0] = -1;
+ fds[1] = -1;
+#if defined(Q_OS_VXWORKS)
+ name[0] = '\0';
+#endif
+}
+
+QThreadPipe::~QThreadPipe()
+{
+ if (fds[0] >= 0)
+ close(fds[0]);
+
+ if (fds[1] >= 0)
+ close(fds[1]);
+
+#if defined(Q_OS_VXWORKS)
+ pipeDevDelete(name, true);
+#endif
+}
+
#if defined(Q_OS_VXWORKS)
static void initThreadPipeFD(int fd)
{
@@ -112,103 +134,110 @@ static void initThreadPipeFD(int fd)
}
#endif
-QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
+bool QThreadPipe::init()
{
- bool pipefail = false;
-
- // initialize the common parts of the event loop
#if defined(Q_OS_NACL)
// do nothing.
#elif defined(Q_OS_VXWORKS)
- char name[20];
qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
// make sure there is no pipe with this name
pipeDevDelete(name, true);
+
// create the pipe
if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) {
- perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe device");
- pipefail = true;
- } else {
- if ((thread_pipe[0] = open(name, O_RDWR, 0)) < 0) {
- perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
- pipefail = true;
- } else {
- initThreadPipeFD(thread_pipe[0]);
- thread_pipe[1] = thread_pipe[0];
- }
+ perror("QThreadPipe: Unable to create thread pipe device %s", name);
+ return false;
}
+
+ if ((fds[0] = open(name, O_RDWR, 0)) < 0) {
+ perror("QThreadPipe: Unable to open pipe device %s", name);
+ return false;
+ }
+
+ initThreadPipeFD(fds[0]);
+ fds[1] = fds[0];
#else
# ifndef QT_NO_EVENTFD
- thread_pipe[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
- if (thread_pipe[0] != -1)
- thread_pipe[1] = -1;
- else // fall through the next "if"
+ if ((fds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)) >= 0)
+ return true;
# endif
- if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) {
- perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
- pipefail = true;
+ if (qt_safe_pipe(fds, O_NONBLOCK) == -1) {
+ perror("QThreadPipe: Unable to create pipe");
+ return false;
}
#endif
- if (Q_UNLIKELY(pipefail))
- qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
+ return true;
}
-QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
+pollfd QThreadPipe::prepare() const
{
-#if defined(Q_OS_NACL)
- // do nothing.
-#elif defined(Q_OS_VXWORKS)
- close(thread_pipe[0]);
-
- char name[20];
- qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
+ return make_pollfd(fds[0], POLLIN);
+}
- pipeDevDelete(name, true);
-#else
- // cleanup the common parts of the event loop
- close(thread_pipe[0]);
- if (thread_pipe[1] != -1)
- close(thread_pipe[1]);
+void QThreadPipe::wakeUp()
+{
+ if (wakeUps.testAndSetAcquire(0, 1)) {
+#ifndef QT_NO_EVENTFD
+ if (fds[1] == -1) {
+ // eventfd
+ eventfd_t value = 1;
+ int ret;
+ EINTR_LOOP(ret, eventfd_write(fds[0], value));
+ return;
+ }
#endif
-
- // cleanup timers
- qDeleteAll(timerList);
+ char c = 0;
+ qt_safe_write(fds[1], &c, 1);
+ }
}
-int QEventDispatcherUNIXPrivate::processThreadWakeUp(const pollfd &pfd)
+int QThreadPipe::check(const pollfd &pfd)
{
- Q_ASSERT(pfd.fd == thread_pipe[0]);
+ Q_ASSERT(pfd.fd == fds[0]);
+
+ char c[16];
+ const int readyread = pfd.revents & POLLIN;
- if (pfd.revents & POLLIN) {
- // some other thread woke us up... consume the data on the thread pipe so that
- // select doesn't immediately return next time
+ if (readyread) {
+ // consume the data on the thread pipe so that
+ // poll doesn't immediately return next time
#if defined(Q_OS_VXWORKS)
- char c[16];
- ::read(thread_pipe[0], c, sizeof(c));
- ::ioctl(thread_pipe[0], FIOFLUSH, 0);
+ ::read(fds[0], c, sizeof(c));
+ ::ioctl(fds[0], FIOFLUSH, 0);
#else
# ifndef QT_NO_EVENTFD
- if (thread_pipe[1] == -1) {
+ if (fds[1] == -1) {
// eventfd
eventfd_t value;
- eventfd_read(thread_pipe[0], &value);
+ eventfd_read(fds[0], &value);
} else
# endif
{
- char c[16];
- while (::read(thread_pipe[0], c, sizeof(c)) > 0) {
- }
+ while (::read(fds[0], c, sizeof(c)) > 0) {}
}
#endif
+
if (!wakeUps.testAndSetRelease(1, 0)) {
// hopefully, this is dead code
- qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!");
+ qWarning("QThreadPipe: internal error, wakeUps.testAndSetRelease(1, 0) failed!");
}
- return 1;
}
- return 0;
+
+ return readyread;
+}
+
+QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
+{
+ if (Q_UNLIKELY(threadPipe.init() == false))
+ qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
+}
+
+QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
+{
+ // cleanup timers
+ qDeleteAll(timerList);
}
void QEventDispatcherUNIXPrivate::setSocketNotifierPending(QSocketNotifier *notifier)
@@ -465,7 +494,7 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
d->pollfds.append(make_pollfd(it.key(), it.value().events()));
// This must be last, as it's popped off the end below
- d->pollfds.append(make_pollfd(d->thread_pipe[0], POLLIN));
+ d->pollfds.append(d->threadPipe.prepare());
int nevents = 0;
@@ -476,7 +505,7 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
case 0:
break;
default:
- nevents += d->processThreadWakeUp(d->pollfds.takeLast());
+ nevents += d->threadPipe.check(d->pollfds.takeLast());
if (include_notifiers)
nevents += d->activateSocketNotifiers();
break;
@@ -511,19 +540,7 @@ int QEventDispatcherUNIX::remainingTime(int timerId)
void QEventDispatcherUNIX::wakeUp()
{
Q_D(QEventDispatcherUNIX);
- if (d->wakeUps.testAndSetAcquire(0, 1)) {
-#ifndef QT_NO_EVENTFD
- if (d->thread_pipe[1] == -1) {
- // eventfd
- eventfd_t value = 1;
- int ret;
- EINTR_LOOP(ret, eventfd_write(d->thread_pipe[0], value));
- return;
- }
-#endif
- char c = 0;
- qt_safe_write( d->thread_pipe[1], &c, 1 );
- }
+ d->threadPipe.wakeUp();
}
void QEventDispatcherUNIX::interrupt()
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index b401c07040..d728040343 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -75,6 +75,27 @@ struct Q_CORE_EXPORT QSocketNotifierSetUNIX Q_DECL_FINAL
Q_DECLARE_TYPEINFO(QSocketNotifierSetUNIX, Q_PRIMITIVE_TYPE);
+struct QThreadPipe
+{
+ QThreadPipe();
+ ~QThreadPipe();
+
+ bool init();
+ pollfd prepare() const;
+
+ void wakeUp();
+ int check(const pollfd &pfd);
+
+ // note for eventfd(7) support:
+ // if fds[1] is -1, then eventfd(7) is in use and is stored in fds[0]
+ int fds[2];
+ QAtomicInt wakeUps;
+
+#if defined(Q_OS_VXWORKS)
+ static const int len_name = 20;
+ char name[len_name];
+#endif
+};
class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher
{
@@ -114,26 +135,19 @@ public:
QEventDispatcherUNIXPrivate();
~QEventDispatcherUNIXPrivate();
- int processThreadWakeUp(const pollfd &pfd);
-
int activateTimers();
void markPendingSocketNotifiers();
int activateSocketNotifiers();
void setSocketNotifierPending(QSocketNotifier *notifier);
- // note for eventfd(7) support:
- // if thread_pipe[1] is -1, then eventfd(7) is in use and is stored in thread_pipe[0]
- int thread_pipe[2];
-
+ QThreadPipe threadPipe;
QVector<pollfd> pollfds;
QHash<int, QSocketNotifierSetUNIX> socketNotifiers;
QVector<QSocketNotifier *> pendingNotifiers;
QTimerInfoList timerList;
-
- QAtomicInt wakeUps;
QAtomicInt interrupt; // bool
};