summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Kehres <jkehres@rim.com>2012-03-23 10:43:44 -0400
committerQt by Nokia <qt-info@nokia.com>2012-04-24 19:36:55 +0200
commit0723e14699704c35d5d61fa7f5e9f3bdbb378afa (patch)
treec24951538714dd0e53c1b1785d64c34072191187
parent77a816c00d80780f81dfcd723c0a287f2ddf660e (diff)
Integrate Blackberry Platform Services (BPS) with Qt event loop.
This ensures interoperability between the Blackbery C and C++ APIs and makes it easier to expose platform services in C++ that are exposed in BPS - since events from both APIs can be processed on the same thread. Change-Id: I7270adc64c26396f66d9126141500d5e58be51e7 Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com> Reviewed-by: Giuseppe D'Angelo <dangelog@gmail.com> Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
-rw-r--r--src/corelib/kernel/kernel.pri7
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp14
-rw-r--r--src/corelib/kernel/qeventdispatcher_blackberry.cpp262
-rw-r--r--src/corelib/kernel/qeventdispatcher_blackberry_p.h96
-rw-r--r--src/corelib/thread/qthread_unix.cpp17
5 files changed, 389 insertions, 7 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 4b81087e2f..bef2929214 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -136,3 +136,10 @@ vxworks {
kernel/qfunctions_vxworks.h
}
+blackberry {
+ SOURCES += \
+ kernel/qeventdispatcher_blackberry.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_blackberry_p.h
+}
+
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index d188ccbc9a..95c80cad20 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -67,10 +67,14 @@
#include <private/qlocale_p.h>
#if defined(Q_OS_UNIX)
-# if !defined(QT_NO_GLIB)
-# include "qeventdispatcher_glib_p.h"
+# if defined(Q_OS_BLACKBERRY)
+# include "qeventdispatcher_blackberry_p.h"
+# else
+# if !defined(QT_NO_GLIB)
+# include "qeventdispatcher_glib_p.h"
+# endif
+# include "qeventdispatcher_unix_p.h"
# endif
-# include "qeventdispatcher_unix_p.h"
#endif
#ifdef Q_OS_WIN
@@ -328,12 +332,16 @@ void QCoreApplicationPrivate::createEventDispatcher()
{
Q_Q(QCoreApplication);
#if defined(Q_OS_UNIX)
+# if defined(Q_OS_BLACKBERRY)
+ eventDispatcher = new QEventDispatcherBlackberry(q);
+# else
# if !defined(QT_NO_GLIB)
if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
eventDispatcher = new QEventDispatcherGlib(q);
else
# endif
eventDispatcher = new QEventDispatcherUNIX(q);
+# endif
#elif defined(Q_OS_WIN)
eventDispatcher = new QEventDispatcherWin32(q);
#else
diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
new file mode 100644
index 0000000000..462e359bf3
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_blackberry_p.h"
+#include "qsocketnotifier.h"
+#include "qdebug.h"
+
+#include <bps/bps.h>
+#include <bps/event.h>
+
+struct bpsIOHandlerData {
+ bpsIOHandlerData()
+ : count(0), readfds(0), writefds(0), exceptfds(0)
+ {
+ }
+
+ int count;
+ fd_set *readfds;
+ fd_set *writefds;
+ fd_set *exceptfds;
+};
+
+static int bpsIOReadyDomain = -1;
+
+static int bpsIOHandler(int fd, int io_events, void *data)
+{
+ // decode callback payload
+ bpsIOHandlerData *ioData = static_cast<bpsIOHandlerData*>(data);
+
+ // check if first file is ready
+ bool firstReady = (ioData->count == 0);
+
+ // update ready state of file
+ if (io_events & BPS_IO_INPUT) {
+ FD_SET(fd, ioData->readfds);
+ ioData->count++;
+ }
+
+ if (io_events & BPS_IO_OUTPUT) {
+ FD_SET(fd, ioData->writefds);
+ ioData->count++;
+ }
+
+ if (io_events & BPS_IO_EXCEPT) {
+ FD_SET(fd, ioData->exceptfds);
+ ioData->count++;
+ }
+
+ // force bps_get_event() to return immediately by posting an event to ourselves;
+ // but this only needs to happen once if multiple files become ready at the same time
+ if (firstReady) {
+ // create IO ready event
+ bps_event_t *event;
+ int result = bps_event_create(&event, bpsIOReadyDomain, 0, NULL, NULL);
+ if (result != BPS_SUCCESS) {
+ qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_event_create() failed");
+ return BPS_FAILURE;
+ }
+
+ // post IO ready event to our thread
+ result = bps_push_event(event);
+ if (result != BPS_SUCCESS) {
+ qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_push_event() failed");
+ bps_event_destroy(event);
+ return BPS_FAILURE;
+ }
+ }
+
+ return BPS_SUCCESS;
+}
+
+QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberryPrivate()
+ : ioData(new bpsIOHandlerData)
+{
+ // prepare to use BPS
+ int result = bps_initialize();
+ if (result != BPS_SUCCESS)
+ qFatal("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_initialize() failed");
+
+ // get domain for IO ready events - ignoring race condition here for now
+ if (bpsIOReadyDomain == -1) {
+ bpsIOReadyDomain = bps_register_domain();
+ if (bpsIOReadyDomain == -1)
+ qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_register_domain() failed");
+ }
+
+ // \TODO Reinstate this when bps is fixed. See comment in select() below.
+ // Register thread_pipe[0] with bps
+ /*
+ int io_events = BPS_IO_INPUT;
+ result = bps_add_fd(thread_pipe[0], io_events, &bpsIOHandler, ioData.data());
+ if (result != BPS_SUCCESS)
+ qWarning() << Q_FUNC_INFO << "bps_add_fd() failed";
+ */
+}
+
+QEventDispatcherBlackberryPrivate::~QEventDispatcherBlackberryPrivate()
+{
+ // we're done using BPS
+ bps_shutdown();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+QEventDispatcherBlackberry::QEventDispatcherBlackberry(QObject *parent)
+ : QEventDispatcherUNIX(*new QEventDispatcherBlackberryPrivate, parent)
+{
+}
+
+QEventDispatcherBlackberry::QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent)
+ : QEventDispatcherUNIX(dd, parent)
+{
+}
+
+QEventDispatcherBlackberry::~QEventDispatcherBlackberry()
+{
+}
+
+void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+
+ // Call the base Unix implementation. Needed to allow select() to be called correctly
+ QEventDispatcherUNIX::registerSocketNotifier(notifier);
+
+ // Register the fd with bps
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+
+ int io_events = 0;
+ switch (type) {
+ case QSocketNotifier::Read:
+ io_events |= BPS_IO_INPUT;
+ break;
+ case QSocketNotifier::Write:
+ io_events |= BPS_IO_OUTPUT;
+ break;
+ case QSocketNotifier::Exception:
+ default:
+ io_events |= BPS_IO_EXCEPT;
+ break;
+ }
+
+ Q_D(QEventDispatcherBlackberry);
+ int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data());
+ if (result != BPS_SUCCESS)
+ qWarning() << Q_FUNC_INFO << "bps_add_fd() failed";
+}
+
+void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ // Unregister the fd with bps
+ int sockfd = notifier->socket();
+ int result = bps_remove_fd(sockfd);
+ if (result != BPS_SUCCESS)
+ qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed";
+
+ // Allow the base Unix implementation to unregister the fd too
+ QEventDispatcherUNIX::unregisterSocketNotifier(notifier);
+}
+
+int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout)
+{
+ Q_UNUSED(nfds);
+
+ // prepare file sets for bps callback
+ Q_D(QEventDispatcherBlackberry);
+ d->ioData->count = 0;
+ d->ioData->readfds = readfds;
+ d->ioData->writefds = writefds;
+ d->ioData->exceptfds = exceptfds;
+
+ // \TODO Remove this when bps is fixed
+ //
+ // Work around a bug in BPS with which if we register the thread_pipe[0] fd with bps in the
+ // private class' ctor once only then we get spurious notifications that thread_pipe[0] is
+ // ready for reading. The first time the notification is correct and the pipe is emptied in
+ // the calling doSelect() function. The 2nd notification is an error and the resulting attempt
+ // to read and call to wakeUps.testAndSetRelease(1, 0) fails as there has been no intervening
+ // call to QEventDispatcherUNIX::wakeUp().
+ //
+ // Registering thread_pipe[0] here and unregistering it at the end of this call works around
+ // this issue.
+ int io_events = BPS_IO_INPUT;
+ int result = bps_add_fd(d->thread_pipe[0], io_events, &bpsIOHandler, d->ioData.data());
+ if (result != BPS_SUCCESS)
+ qWarning() << Q_FUNC_INFO << "bps_add_fd() failed";
+
+ // reset all file sets
+ if (readfds)
+ FD_ZERO(readfds);
+
+ if (writefds)
+ FD_ZERO(writefds);
+
+ if (exceptfds)
+ FD_ZERO(exceptfds);
+
+ // convert timeout to milliseconds
+ int timeout_ms = -1;
+ if (timeout)
+ timeout_ms = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
+
+ // wait for event or file to be ready
+ bps_event_t *event = NULL;
+ result = bps_get_event(&event, timeout_ms);
+ if (result != BPS_SUCCESS)
+ qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed");
+
+ // pass all received events through filter - except IO ready events
+ if (event && bps_event_get_domain(event) != bpsIOReadyDomain)
+ filterEvent((void*)event);
+
+ // \TODO Remove this when bps is fixed (see comment above)
+ result = bps_remove_fd(d->thread_pipe[0]);
+ if (result != BPS_SUCCESS)
+ qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed";
+
+ // the number of bits set in the file sets
+ return d->ioData->count;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_blackberry_p.h b/src/corelib/kernel/qeventdispatcher_blackberry_p.h
new file mode 100644
index 0000000000..b996bc7ee7
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_blackberry_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_BLACKBERRY_P_H
+#define QEVENTDISPATCHER_BLACKBERRY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qeventdispatcher_unix_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherBlackberryPrivate;
+
+class Q_CORE_EXPORT QEventDispatcherBlackberry : public QEventDispatcherUNIX
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherBlackberry)
+
+public:
+ explicit QEventDispatcherBlackberry(QObject *parent = 0);
+ ~QEventDispatcherBlackberry();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+protected:
+ QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent = 0);
+
+ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout);
+};
+
+struct bpsIOHandlerData;
+
+class Q_CORE_EXPORT QEventDispatcherBlackberryPrivate : public QEventDispatcherUNIXPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherBlackberry)
+
+public:
+ QEventDispatcherBlackberryPrivate();
+ ~QEventDispatcherBlackberryPrivate();
+
+ QScopedPointer<bpsIOHandlerData> ioData;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_BLACKBERRY_P_H
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 3af54c7fc7..a47115cfac 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -44,11 +44,15 @@
#include "qplatformdefs.h"
#include <private/qcoreapplication_p.h>
-#if !defined(QT_NO_GLIB)
-# include "../kernel/qeventdispatcher_glib_p.h"
-#endif
-#include <private/qeventdispatcher_unix_p.h>
+#if defined(Q_OS_BLACKBERRY)
+# include <private/qeventdispatcher_blackberry_p.h>
+#else
+# if !defined(QT_NO_GLIB)
+# include "../kernel/qeventdispatcher_glib_p.h"
+# endif
+# include <private/qeventdispatcher_unix_p.h>
+#endif
#include "qthreadstorage.h"
@@ -248,6 +252,9 @@ typedef void*(*QtThreadCallback)(void*);
void QThreadPrivate::createEventDispatcher(QThreadData *data)
{
+#if defined(Q_OS_BLACKBERRY)
+ data->eventDispatcher = new QEventDispatcherBlackberry;
+#else
#if !defined(QT_NO_GLIB)
if (qgetenv("QT_NO_GLIB").isEmpty()
&& qgetenv("QT_NO_THREADED_GLIB").isEmpty()
@@ -256,6 +263,8 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data)
else
#endif
data->eventDispatcher = new QEventDispatcherUNIX;
+#endif
+
data->eventDispatcher->startingUp();
}