summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp67
-rw-r--r--src/corelib/kernel/qcore_symbian_p.cpp104
-rw-r--r--src/corelib/kernel/qcore_symbian_p.h101
-rw-r--r--src/corelib/kernel/qcore_unix_p.h9
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp196
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h20
-rw-r--r--src/corelib/kernel/qfunctions_wince.h4
-rw-r--r--src/corelib/kernel/qmetaobject.cpp53
-rw-r--r--src/corelib/kernel/qmetaobject_p.h6
-rw-r--r--src/corelib/kernel/qobject.cpp183
-rw-r--r--src/corelib/kernel/qobject_p.h20
-rw-r--r--src/corelib/kernel/qobjectdefs.h13
-rw-r--r--src/corelib/kernel/qpointer.cpp10
-rw-r--r--src/corelib/kernel/qsystemerror.cpp4
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp7
-rw-r--r--src/corelib/kernel/qtranslator.cpp152
-rw-r--r--src/corelib/kernel/qtranslator.h6
17 files changed, 789 insertions, 166 deletions
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index e79f87a..2949cd0 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -49,22 +49,51 @@
QT_BEGIN_NAMESPACE
// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
-enum { NumberOfBuckets = 8, FirstBucketSize = 8 };
-
-static const int BucketSize[NumberOfBuckets] =
- { 8, 64, 512, 4096, 32768, 262144, 2097152, 16777216 - 2396744 };
-static const int BucketOffset[NumberOfBuckets] =
- { 0, 8, 72, 584, 4680, 37448, 299592, 2396744 };
-
-static int FirstBucket[FirstBucketSize] = { 1, 2, 3, 4, 5, 6, 7, 8 };
-static QBasicAtomicPointer<int> timerIds[NumberOfBuckets] =
+static const int TimerIdMask = 0x00ffffff;
+static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
+static const int TimerSerialCounter = TimerIdMask + 1;
+static const int MaxTimerId = TimerIdMask;
+
+static int FirstBucket[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
+};
+
+enum {
+ FirstBucketOffset = 0,
+ SecondBucketOffset = sizeof(FirstBucket) / sizeof(FirstBucket[0]),
+ ThirdBucketOffset = 0x100,
+ FourthBucketOffset = 0x1000,
+ FifthBucketOffset = 0x10000,
+ SixthBucketOffset = 0x100000
+};
+
+enum {
+ FirstBucketSize = SecondBucketOffset,
+ SecondBucketSize = ThirdBucketOffset - SecondBucketOffset,
+ ThirdBucketSize = FourthBucketOffset - ThirdBucketOffset,
+ FourthBucketSize = FifthBucketOffset - FourthBucketOffset,
+ FifthBucketSize = SixthBucketOffset - FifthBucketOffset,
+ SixthBucketSize = MaxTimerId - SixthBucketOffset
+};
+
+static const int BucketSize[] = {
+ FirstBucketSize, SecondBucketSize, ThirdBucketSize,
+ FourthBucketSize, FifthBucketSize, SixthBucketSize
+};
+enum { NumberOfBuckets = sizeof(BucketSize) / sizeof(BucketSize[0]) };
+
+static const int BucketOffset[] = {
+ FirstBucketOffset, SecondBucketOffset, ThirdBucketOffset,
+ FourthBucketOffset, FifthBucketOffset, SixthBucketOffset
+};
+
+static QBasicAtomicPointer<int> timerIds[] =
{ Q_BASIC_ATOMIC_INITIALIZER(FirstBucket),
Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0),
- Q_BASIC_ATOMIC_INITIALIZER(0),
- Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0) };
static void timerIdsDestructorFunction()
@@ -77,18 +106,23 @@ Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction)
static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1);
-static const int TimerIdMask = 0x00ffffff;
-static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
-static const int TimerSerialCounter = TimerIdMask + 1;
-
// avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number
static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
{
return (newId & TimerIdMask) | ((oldId + TimerSerialCounter) & TimerSerialMask);
}
+namespace {
+ template<bool> struct QStaticAssertType;
+ template<> struct QStaticAssertType<true> { enum { Value = 1 }; };
+}
+#define q_static_assert(expr) (void)QStaticAssertType<expr>::Value
+
static inline int bucketOffset(int timerId)
{
+ q_static_assert(sizeof BucketSize == sizeof BucketOffset);
+ q_static_assert(sizeof(timerIds) / sizeof(timerIds[0]) == NumberOfBuckets);
+
for (int i = 0; i < NumberOfBuckets; ++i) {
if (timerId < BucketSize[i])
return i;
@@ -187,7 +221,8 @@ void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
int at = bucketIndex(bucket, which);
int *b = timerIds[bucket];
- Q_ASSERT(b[at] == -timerId);
+ Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId",
+ "Internal error: timer ID not found");
int freeId, newTimerId;
do {
diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp
index 801d63f..c717cb9 100644
--- a/src/corelib/kernel/qcore_symbian_p.cpp
+++ b/src/corelib/kernel/qcore_symbian_p.cpp
@@ -44,6 +44,7 @@
#include <e32uid.h>
#include "qcore_symbian_p.h"
#include <string>
+#include <in_sock.h>
QT_BEGIN_NAMESPACE
@@ -203,6 +204,11 @@ private:
RFs iFs;
};
+uint qHash(const RSubSessionBase& key)
+{
+ return qHash(key.SubSessionHandle());
+}
+
Q_GLOBAL_STATIC(QS60RFsSession, qt_s60_RFsSession);
Q_CORE_EXPORT RFs& qt_s60GetRFs()
@@ -210,4 +216,102 @@ Q_CORE_EXPORT RFs& qt_s60GetRFs()
return qt_s60_RFsSession()->GetRFs();
}
+QSymbianSocketManager::QSymbianSocketManager() :
+ iNextSocket(0), iDefaultConnection(0)
+{
+ TSessionPref preferences;
+ // ### In future this could be changed to KAfInet6 when that is more common than IPv4
+ preferences.iAddrFamily = KAfInet;
+ preferences.iProtocol = KProtocolInetIp;
+ //use global message pool, as we do not know how many sockets app will use
+ //TODO: is this the right choice?
+ qt_symbian_throwIfError(iSocketServ.Connect(preferences, -1));
+ qt_symbian_throwIfError(iSocketServ.ShareAuto());
+}
+
+QSymbianSocketManager::~QSymbianSocketManager()
+{
+ iSocketServ.Close();
+ if(!socketMap.isEmpty()) {
+ qWarning("leaked %d sockets on exit", socketMap.count());
+ }
+}
+
+RSocketServ& QSymbianSocketManager::getSocketServer() {
+ return iSocketServ;
+}
+
+int QSymbianSocketManager::addSocket(const RSocket& socket) {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ Q_ASSERT(!socketMap.contains(sock));
+ if(socketMap.contains(sock))
+ return socketMap.value(sock);
+ // allocate socket number
+ int guard = 0;
+ while(reverseSocketMap.contains(iNextSocket)) {
+ iNextSocket++;
+ iNextSocket %= max_sockets;
+ guard++;
+ if(guard > max_sockets)
+ return -1;
+ }
+ int id = iNextSocket;
+
+ socketMap[sock] = id;
+ reverseSocketMap[id] = sock;
+ return id + socket_offset;
+}
+
+bool QSymbianSocketManager::removeSocket(const RSocket &socket) {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ if(!socketMap.contains(sock))
+ return false;
+ int id = socketMap.value(sock);
+ socketMap.remove(sock);
+ reverseSocketMap.remove(id);
+ return true;
+}
+
+int QSymbianSocketManager::lookupSocket(const RSocket& socket) const {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ if(!socketMap.contains(sock))
+ return -1;
+ int id = socketMap.value(sock);
+ return id + socket_offset;
+}
+
+bool QSymbianSocketManager::lookupSocket(int fd, RSocket& socket) const {
+ QMutexLocker l(&iMutex);
+ int id = fd - socket_offset;
+ if(!reverseSocketMap.contains(id))
+ return false;
+ socket = reverseSocketMap.value(id);
+ return true;
+}
+
+void QSymbianSocketManager::setDefaultConnection(RConnection* con)
+{
+ iDefaultConnection = con;
+}
+
+RConnection* QSymbianSocketManager::defaultConnection() const
+{
+ return iDefaultConnection;
+}
+
+Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager);
+
+QSymbianSocketManager& QSymbianSocketManager::instance()
+{
+ return *(qt_symbianSocketManager());
+}
+
+Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer()
+{
+ return QSymbianSocketManager::instance().getSocketServer();
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h
index 5b48689..cbe84a8 100644
--- a/src/corelib/kernel/qcore_symbian_p.h
+++ b/src/corelib/kernel/qcore_symbian_p.h
@@ -55,10 +55,12 @@
#include <e32std.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qmutex.h>
#include <qstring.h>
#include <qrect.h>
#include <qhash.h>
#include <f32file.h>
+#include <es_sock.h>
#define QT_LSTRING2(x) L##x
#define QT_LSTRING(x) QT_LSTRING2(x)
@@ -154,6 +156,7 @@ enum S60PluginFuncOrdinals
Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal);
Q_CORE_EXPORT RFs& qt_s60GetRFs();
+Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer();
// Defined in qlocale_symbian.cpp.
Q_CORE_EXPORT QByteArray qt_symbianLocaleName(int code);
@@ -174,6 +177,104 @@ struct QScopedPointerRCloser
}
};
+//Wrapper for RSocket so it can be used as a key in QHash or QMap
+class QHashableSocket : public RSocket
+{
+public:
+ bool operator==(const QHashableSocket &other) const
+ {
+ return SubSessionHandle() == other.SubSessionHandle()
+ && Session().Handle() == other.Session().Handle();
+ }
+ bool operator<(const QHashableSocket &other) const
+ {
+ if (Session().Handle() == other.Session().Handle())
+ return SubSessionHandle() < other.SubSessionHandle();
+ return Session().Handle() < other.Session().Handle();
+ }
+};
+
+uint qHash(const RSubSessionBase& key);
+
+/*!
+ \internal
+ This class exists in QtCore for the benefit of QSocketNotifier, which uses integer
+ file descriptors in its public API.
+ So we need a way to map between int and RSocket.
+ Additionally, it is used to host the global RSocketServ session
+*/
+class Q_CORE_EXPORT QSymbianSocketManager
+{
+public:
+ QSymbianSocketManager();
+ ~QSymbianSocketManager();
+
+ /*!
+ \internal
+ \return handle to the socket server
+ */
+ RSocketServ& getSocketServer();
+ /*!
+ \internal
+ Adds a symbian socket to the global map
+ \param an open socket
+ \return pseudo file descriptor, -1 if out of resources
+ */
+ int addSocket(const RSocket &sock);
+ /*!
+ \internal
+ Removes a symbian socket from the global map
+ \param an open socket
+ \return true if the socket was in the map
+ */
+ bool removeSocket(const RSocket &sock);
+ /*!
+ \internal
+ Get pseudo file descriptor for a socket
+ \param an open socket
+ \return integer handle, or -1 if not in map
+ */
+ int lookupSocket(const RSocket &sock) const;
+ /*!
+ \internal
+ Get socket for a pseudo file descriptor
+ \param an open socket fd
+ \param sock (out) socket handle
+ \return true on success or false if not in map
+ */
+ bool lookupSocket(int fd, RSocket& sock) const;
+
+ /*!
+ \internal
+ Set the default connection to use for new sockets
+ \param an open connection
+ */
+ void setDefaultConnection(RConnection* con);
+ /*!
+ \internal
+ Get the default connection to use for new sockets
+ \return the connection, or null pointer if there is none set
+ */
+ RConnection *defaultConnection() const;
+
+ /*!
+ \internal
+ Gets a reference to the singleton socket manager
+ */
+ static QSymbianSocketManager& instance();
+private:
+ int allocateSocket();
+
+ const static int max_sockets = 0x20000; //covers all TCP and UDP ports, probably run out of memory first
+ const static int socket_offset = 0x40000000; //hacky way of separating sockets from file descriptors
+ int iNextSocket;
+ QHash<QHashableSocket, int> socketMap;
+ QHash<int, RSocket> reverseSocketMap;
+ mutable QMutex iMutex;
+ RSocketServ iSocketServ;
+ RConnection *iDefaultConnection;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 2e84f3b..33df0da 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -319,6 +319,15 @@ timeval qt_gettime(); // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
const struct timeval *tv);
+// according to X/OPEN we have to define semun ourselves
+// we use prefix as on some systems sem.h will have it
+struct semid_ds;
+union qt_semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* array for GETALL, SETALL */
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index 4c01bde..e0eeb08 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -135,7 +135,7 @@ private:
* The QCompleteDeferredAOs class is a special object that runs after all others, which will
* reactivate the objects that were previously not run.
*/
-inline QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
+QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
: CActive(priority),
m_dispatcher(dispatcher),
m_hasAlreadyRun(false),
@@ -167,12 +167,25 @@ bool QActiveObject::maybeQueueForLater()
}
}
+bool QActiveObject::maybeDeferSocketEvent()
+{
+ Q_ASSERT(!m_hasRunAgain);
+ Q_ASSERT(m_dispatcher);
+ if (!m_dispatcher->areSocketEventsBlocked()) {
+ return false;
+ }
+ m_hasRunAgain = true;
+ m_dispatcher->addDeferredSocketActiveObject(this);
+ return true;
+}
+
void QActiveObject::reactivateAndComplete()
{
+ TInt error = iStatus.Int();
iStatus = KRequestPending;
SetActive();
TRequestStatus *status = &iStatus;
- QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ QEventDispatcherSymbian::RequestComplete(status, error);
m_hasRunAgain = false;
m_hasAlreadyRun = false;
@@ -181,6 +194,7 @@ void QActiveObject::reactivateAndComplete()
QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher)
: QActiveObject(WAKE_UP_PRIORITY, dispatcher)
{
+ m_hostThreadId = RThread().Id();
CActiveScheduler::Add(this);
iStatus = KRequestPending;
SetActive();
@@ -196,6 +210,15 @@ void QWakeUpActiveObject::DoCancel()
if (iStatus.Int() == KRequestPending) {
TRequestStatus *status = &iStatus;
QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ } else if (IsActive() && m_hostThreadId != RThread().Id()) {
+ // This is being cancelled in the adopted monitor thread, which can happen if an adopted thread with
+ // an event loop has exited. The event loop creates an event dispatcher with this active object, which may be complete but not run on exit.
+ // We force a cancellation in this thread, because a) the object cannot be deleted while active and b) without a cancellation
+ // the thread semaphore will be one count down.
+ // It is possible for this problem to affect other active objects. They symptom would be that finished signals
+ // from adopted threads are not sent, or they arrive much later than they should.
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
}
}
@@ -211,8 +234,10 @@ void QWakeUpActiveObject::RunL()
QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
: QActiveObject((timerInfo->interval) ? TIMER_PRIORITY : NULLTIMER_PRIORITY , dispatcher),
- m_timerInfo(timerInfo)
+ m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0)
{
+ // start the timeout timer to ensure initialisation
+ m_timeoutTimer.start();
}
QTimerActiveObject::~QTimerActiveObject()
@@ -256,10 +281,23 @@ void QTimerActiveObject::StartTimer()
m_rTimer.After(iStatus, MAX_SYMBIAN_TIMEOUT_MS * 1000);
m_timerInfo->msLeft -= MAX_SYMBIAN_TIMEOUT_MS;
} else {
- //HighRes gives the 1ms accuracy expected by Qt, the +1 is to ensure that
- //"Timers will never time out earlier than the specified timeout value"
- //condition is always met.
- m_rTimer.HighRes(iStatus, (m_timerInfo->msLeft + 1) * 1000);
+ // this algorithm implements drift correction for repeating timers
+ // calculate how late we are for this event
+ int timeSinceLastEvent = m_timeoutTimer.restart();
+ int overshoot = timeSinceLastEvent - m_expectedTimeSinceLastEvent;
+ if (overshoot > m_timerInfo->msLeft) {
+ // we skipped a whole timeout, restart from here
+ overshoot = 0;
+ }
+ // calculate when the next event should happen
+ int waitTime = m_timerInfo->msLeft - overshoot;
+ m_expectedTimeSinceLastEvent = waitTime;
+ // limit the actual ms wait time to avoid wild corrections
+ // this will cause the real event time to slowly drift back to the expected event time
+ // measurements show that Symbian timers always fire 1 or 2 ms late
+ const int limit = 4;
+ waitTime = qMax(m_timerInfo->msLeft - limit, waitTime);
+ m_rTimer.HighRes(iStatus, waitTime * 1000);
m_timerInfo->msLeft = 0;
}
SetActive();
@@ -306,6 +344,8 @@ void QTimerActiveObject::Start()
if (!m_rTimer.Handle()) {
qt_symbian_throwIfError(m_rTimer.CreateLocal());
}
+ m_timeoutTimer.start();
+ m_expectedTimeSinceLastEvent = 0;
StartTimer();
} else {
iStatus = KRequestPending;
@@ -635,10 +675,28 @@ void QSocketActiveObject::DoCancel()
void QSocketActiveObject::RunL()
{
+ if (maybeDeferSocketEvent())
+ return;
if (maybeQueueForLater())
return;
- QT_TRYCATCH_LEAVING(m_dispatcher->socketFired(this));
+ QT_TRYCATCH_LEAVING(run());
+}
+
+void QSocketActiveObject::run()
+{
+ QEvent e(QEvent::SockAct);
+ m_inSocketEvent = true;
+ QCoreApplication::sendEvent(m_notifier, &e);
+ m_inSocketEvent = false;
+
+ if (m_deleteLater) {
+ delete this;
+ } else {
+ iStatus = KRequestPending;
+ SetActive();
+ m_dispatcher->reactivateSocketNotifier(m_notifier);
+ }
}
void QSocketActiveObject::deleteLater()
@@ -849,6 +907,14 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
CActiveScheduler::Current()->WaitForAnyRequest();
} else {
if (thread.RequestCount() == 0) {
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ if (idleDetectorThread()->hasRun()) {
+ m_lastIdleRequestTimer.start();
+ idleDetectorThread()->kick();
+ } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) {
+ User::AfterHighRes(m_delay);
+ }
+#endif
break;
}
// This one should return without delay.
@@ -934,27 +1000,6 @@ void QEventDispatcherSymbian::timerFired(int timerId)
return;
}
-void QEventDispatcherSymbian::socketFired(QSocketActiveObject *socketAO)
-{
- if (m_noSocketEvents) {
- m_deferredSocketEvents.append(socketAO);
- return;
- }
-
- QEvent e(QEvent::SockAct);
- socketAO->m_inSocketEvent = true;
- QCoreApplication::sendEvent(socketAO->m_notifier, &e);
- socketAO->m_inSocketEvent = false;
-
- if (socketAO->m_deleteLater) {
- delete socketAO;
- } else {
- socketAO->iStatus = KRequestPending;
- socketAO->SetActive();
- reactivateSocketNotifier(socketAO->m_notifier);
- }
-}
-
void QEventDispatcherSymbian::wakeUpWasCalled()
{
// The reactivation should happen in RunL, right before the call to this function.
@@ -1015,6 +1060,12 @@ inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *obje
inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *object)
{
m_deferredActiveObjects.removeAll(object);
+ m_deferredSocketEvents.removeAll(object);
+}
+
+inline void QEventDispatcherSymbian::addDeferredSocketActiveObject(QActiveObject *object)
+{
+ m_deferredSocketEvents.append(object);
}
void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion()
@@ -1040,7 +1091,8 @@ bool QEventDispatcherSymbian::sendDeferredSocketEvents()
bool sentAnyEvents = false;
while (!m_deferredSocketEvents.isEmpty()) {
sentAnyEvents = true;
- socketFired(m_deferredSocketEvents.takeFirst());
+ QActiveObject *object = m_deferredSocketEvents.takeFirst();
+ object->reactivateAndComplete();
}
return sentAnyEvents;
@@ -1059,6 +1111,8 @@ bool QEventDispatcherSymbian::hasPendingEvents()
void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier )
{
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier);
Q_CHECK_PTR(socketAO);
m_notifiers.insert(notifier, socketAO);
@@ -1067,6 +1121,8 @@ void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifie
void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notifier )
{
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
if (m_selectThread)
m_selectThread->cancelSocketEvents(notifier);
if (m_notifiers.contains(notifier)) {
@@ -1169,6 +1225,86 @@ void CQtActiveScheduler::Error(TInt aError) const
QT_CATCH (const std::bad_alloc&) {} // ignore alloc fails, nothing more can be done
}
+bool QActiveObject::wait(CActive* ao, int ms)
+{
+ if (!ao->IsActive())
+ return true; //request already complete
+ bool timedout = false;
+ if (ms > 0) {
+ TRequestStatus tstat;
+ RTimer t;
+ if (KErrNone != t.CreateLocal())
+ return false;
+ t.HighRes(tstat, ms*1000);
+ User::WaitForRequest(tstat, ao->iStatus);
+ if (tstat != KRequestPending) {
+ timedout = true;
+ } else {
+ t.Cancel();
+ //balance thread semaphore
+ User::WaitForRequest(tstat);
+ }
+ t.Close();
+ } else {
+ User::WaitForRequest(ao->iStatus);
+ }
+ if (timedout)
+ return false;
+
+ //evil cast to allow calling of protected virtual
+ ((QActiveObject*)ao)->RunL();
+
+ //clear active & pending flags
+ ao->iStatus = TRequestStatus();
+
+ return true;
+}
+
+bool QActiveObject::wait(QList<CActive*> aos, int ms)
+{
+ QVector<TRequestStatus*> stati;
+ stati.reserve(aos.count() + 1);
+ foreach (CActive* ao, aos) {
+ if (!ao->IsActive())
+ return true; //request already complete
+ stati.append(&(ao->iStatus));
+ }
+ bool timedout = false;
+ TRequestStatus tstat;
+ RTimer t;
+ if (ms > 0) {
+ if (KErrNone != t.CreateLocal())
+ return false;
+ t.HighRes(tstat, ms*1000);
+ stati.append(&tstat);
+ }
+ User::WaitForNRequest(stati.data(), stati.count());
+ if (ms > 0) {
+ if (tstat != KRequestPending) {
+ timedout = true;
+ } else {
+ t.Cancel();
+ //balance thread semaphore
+ User::WaitForRequest(tstat);
+ }
+ t.Close();
+ }
+ if (timedout)
+ return false;
+
+ foreach (CActive* ao, aos) {
+ if (ao->iStatus != KRequestPending) {
+ //evil cast to allow calling of protected virtual
+ ((QActiveObject*)ao)->RunL();
+
+ //clear active & pending flags
+ ao->iStatus = TRequestStatus();
+ break; //only call one
+ }
+ }
+ return true;
+}
+
QT_END_NAMESPACE
#include "moc_qeventdispatcher_symbian_p.cpp"
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
index bdb6dce..6fdd4b2 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian_p.h
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -77,16 +77,19 @@ QT_BEGIN_NAMESPACE
class QEventDispatcherSymbian;
class QTimerActiveObject;
-class QActiveObject : public CActive
+class Q_CORE_EXPORT QActiveObject : public CActive
{
public:
QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher);
~QActiveObject();
bool maybeQueueForLater();
+ bool maybeDeferSocketEvent();
void reactivateAndComplete();
+ static bool wait(CActive* ao, int ms);
+ static bool wait(QList<CActive*> aos, int ms);
protected:
QEventDispatcherSymbian *m_dispatcher;
@@ -107,6 +110,9 @@ public:
protected:
void DoCancel();
void RunL();
+
+private:
+ TThreadId m_hostThreadId;
};
struct SymbianTimerInfo : public QSharedData
@@ -144,6 +150,8 @@ private:
private:
SymbianTimerInfo *m_timerInfo;
+ QElapsedTimer m_timeoutTimer;
+ int m_expectedTimeSinceLastEvent;
RTimer m_rTimer;
};
@@ -174,6 +182,7 @@ public:
protected:
void DoCancel();
void RunL();
+ void run();
private:
QSocketNotifier *m_notifier;
@@ -242,7 +251,6 @@ public:
void closingDown();
void timerFired(int timerId);
- void socketFired(QSocketActiveObject *socketAO);
void wakeUpWasCalled();
void reactivateSocketNotifier(QSocketNotifier *notifier);
@@ -254,6 +262,9 @@ public:
inline int iterationCount() const { return m_iterationCount; }
+ void addDeferredSocketActiveObject(QActiveObject *object);
+ inline bool areSocketEventsBlocked() const { return m_noSocketEvents; }
+
static void RequestComplete(TRequestStatus *&status, TInt reason);
static void RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason);
@@ -279,8 +290,9 @@ private:
unsigned char m_iterationCount;
bool m_insideTimerEvent;
bool m_noSocketEvents;
- QList<QSocketActiveObject *> m_deferredSocketEvents;
-
+ //deferred until socket events are enabled
+ QList<QActiveObject *> m_deferredSocketEvents;
+ //deferred until idle
QList<QActiveObject *> m_deferredActiveObjects;
int m_delay;
diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h
index e282457..fffe407 100644
--- a/src/corelib/kernel/qfunctions_wince.h
+++ b/src/corelib/kernel/qfunctions_wince.h
@@ -84,10 +84,6 @@ errno_t qt_wince__putenv_s(const char*, const char*);
extern "C" {
#endif
-#define SetWindowLongA SetWindowLong
-#define GetWindowLongA GetWindowLong
-#define SendMessageA SendMessage
-
#if !defined(NO_ERRNO_H)
#define NO_ERRNO_H
#endif
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index c5775f6..e671056 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -218,12 +218,20 @@ QObject *QMetaObject::newInstance(QGenericArgument val0,
*/
int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
{
- if (priv(d.data)->revision < 2)
- return 0;
- const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(d.extradata);
- if (!extra || !extra->static_metacall)
- return 0;
- return extra->static_metacall(cl, idx, argv);
+ const QMetaObjectExtraData *extra = reinterpret_cast<const QMetaObjectExtraData *>(d.extradata);
+ if (priv(d.data)->revision >= 6) {
+ if (!extra || !extra->static_metacall)
+ return 0;
+ extra->static_metacall(0, cl, idx, argv);
+ return -1;
+ } else if (priv(d.data)->revision >= 2) {
+ if (!extra || !extra->static_metacall)
+ return 0;
+ typedef int (*OldMetacall)(QMetaObject::Call, int, void **);
+ OldMetacall o = reinterpret_cast<OldMetacall>(extra->static_metacall);
+ return o(cl, idx, argv);
+ }
+ return 0;
}
/*!
@@ -639,20 +647,21 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
*/
int QMetaObject::indexOfSlot(const char *slot) const
{
- int i = QMetaObjectPrivate::indexOfSlot(this, slot, false);
+ const QMetaObject *m = this;
+ int i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, false);
if (i < 0)
- i = QMetaObjectPrivate::indexOfSlot(this, slot, true);
+ i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, true);
+ if (i >= 0)
+ i += m->methodOffset();
return i;
}
-int QMetaObjectPrivate::indexOfSlot(const QMetaObject *m,
+// same as indexOfSignalRelative but for slots.
+int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
const char *slot,
bool normalizeStringData)
{
- int i = indexOfMethodRelative<MethodSlot>(&m, slot, normalizeStringData);
- if (i >= 0)
- i += m->methodOffset();
- return i;
+ return indexOfMethodRelative<MethodSlot>(m, slot, normalizeStringData);
}
static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
@@ -1616,9 +1625,19 @@ bool QMetaMethod::invoke(QObject *object,
val9.data()
};
// recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
- int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
+ int idx_relative = ((handle - priv(mobj->d.data)->methodData) / 5);
+ int idx_offset = mobj->methodOffset();
+ QObjectPrivate::StaticMetaCallFunction callFunction =
+ (QMetaObjectPrivate::get(mobj)->revision >= 6 && mobj->d.extradata)
+ ? reinterpret_cast<const QMetaObjectExtraData *>(mobj->d.extradata)->static_metacall : 0;
+
if (connectionType == Qt::DirectConnection) {
- return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
+ if (callFunction) {
+ callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
+ return true;
+ } else {
+ return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) < 0;
+ }
} else if (connectionType == Qt::QueuedConnection) {
if (returnValue.data()) {
qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
@@ -1652,7 +1671,7 @@ bool QMetaMethod::invoke(QObject *object,
}
}
- QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
+ QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
0, -1, nargs, types, args));
} else { // blocking queued connection
#ifndef QT_NO_THREAD
@@ -1663,7 +1682,7 @@ bool QMetaMethod::invoke(QObject *object,
}
QSemaphore semaphore;
- QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
+ QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
0, -1, 0, 0, param, &semaphore));
semaphore.acquire();
#endif // QT_NO_THREAD
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 210b32c..fdadf4a 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -118,6 +118,7 @@ struct QMetaObjectPrivate
int flags; //since revision 3
int signalCount; //since revision 4
// revision 5 introduces changes in normalized signatures, no new members
+ // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
{ return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
@@ -125,7 +126,7 @@ struct QMetaObjectPrivate
static int indexOfSignalRelative(const QMetaObject **baseObject,
const char* name,
bool normalizeStringData);
- static int indexOfSlot(const QMetaObject *m,
+ static int indexOfSlotRelative(const QMetaObject **m,
const char *slot,
bool normalizeStringData);
static int originalClone(const QMetaObject *obj, int local_method_index);
@@ -136,7 +137,8 @@ struct QMetaObjectPrivate
static void memberIndexes(const QObject *obj, const QMetaMethod &member,
int *signalIndex, int *methodIndex);
static bool connect(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index,
+ const QObject *receiver, int method_index_relative,
+ const QMetaObject *rmeta = 0,
int type = 0, int *types = 0);
static bool disconnect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index,
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index c6153cb..357cfd3 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -263,12 +263,6 @@ public:
: QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
{ }
- const QObjectPrivate::ConnectionList &at(int at) const
- {
- if (at < 0)
- return allsignals;
- return QVector<QObjectPrivate::ConnectionList>::at(at);
- }
QObjectPrivate::ConnectionList &operator[](int at)
{
if (at < 0)
@@ -496,10 +490,12 @@ void QObjectPrivate::clearGuards(QObject *object)
/*! \internal
*/
-QMetaCallEvent::QMetaCallEvent(int id, const QObject *sender, int signalId,
+QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId,
int nargs, int *types, void **args, QSemaphore *semaphore)
- : QEvent(MetaCall), id_(id), sender_(sender), signalId_(signalId),
- nargs_(nargs), types_(types), args_(args), semaphore_(semaphore)
+ : QEvent(MetaCall), sender_(sender), signalId_(signalId),
+ nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
+ callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
{ }
/*! \internal
@@ -522,9 +518,13 @@ QMetaCallEvent::~QMetaCallEvent()
/*! \internal
*/
-int QMetaCallEvent::placeMetaCall(QObject *object)
+void QMetaCallEvent::placeMetaCall(QObject *object)
{
- return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_);
+ if (callFunction_) {
+ callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
+ } else {
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
+ }
}
/*!
@@ -2613,18 +2613,17 @@ bool QObject::connect(const QObject *sender, const char *signal,
++method; // skip code
const QMetaObject *rmeta = receiver->metaObject();
- int method_index = -1;
+ int method_index_relative = -1;
switch (membcode) {
case QSLOT_CODE:
- method_index = QMetaObjectPrivate::indexOfSlot(rmeta, method, false);
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
break;
case QSIGNAL_CODE:
- method_index = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
- if (method_index >= 0)
- method_index += rmeta->methodOffset();
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
break;
}
- if (method_index < 0) {
+
+ if (method_index_relative < 0) {
// check for normalized methods
tmp_method_name = QMetaObject::normalizedSignature(method);
method = tmp_method_name.constData();
@@ -2633,19 +2632,24 @@ bool QObject::connect(const QObject *sender, const char *signal,
rmeta = receiver->metaObject();
switch (membcode) {
case QSLOT_CODE:
- method_index = rmeta->indexOfSlot(method);
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, true);
break;
case QSIGNAL_CODE:
- method_index = rmeta->indexOfSignal(method);
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, true);
break;
}
}
- if (method_index < 0) {
+ if (method_index_relative < 0) {
err_method_notfound(receiver, method_arg, "connect");
err_info_about_objects("connect", sender, receiver);
return false;
}
+
if (!QMetaObject::checkConnectArgs(signal, method)) {
qWarning("QObject::connect: Incompatible sender/receiver arguments"
"\n %s::%s --> %s::%s",
@@ -2660,14 +2664,13 @@ bool QObject::connect(const QObject *sender, const char *signal,
return false;
#ifndef QT_NO_DEBUG
- {
+ if (warnCompat) {
QMetaMethod smethod = smeta->method(signal_absolute_index);
- QMetaMethod rmethod = rmeta->method(method_index);
- if (warnCompat)
- check_and_warn_compat(smeta, smethod, rmeta, rmethod);
+ QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
+ check_and_warn_compat(smeta, smethod, rmeta, rmethod);
}
#endif
- if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types))
+ if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index_relative, rmeta ,type, types))
return false;
const_cast<QObject*>(sender)->connectNotify(signal - 1);
return true;
@@ -2772,7 +2775,7 @@ bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
if (warnCompat)
check_and_warn_compat(smeta, signal, rmeta, method);
#endif
- if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types))
+ if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, 0, type, types))
return false;
const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
@@ -3163,18 +3166,28 @@ bool QMetaObject::connect(const QObject *sender, int signal_index,
{
signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
return QMetaObjectPrivate::connect(sender, signal_index,
- receiver, method_index, type, types);
+ receiver, method_index,
+ 0, //FIXME, we could speed this connection up by computing the relative index
+ type, types);
}
/*! \internal
Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
+
+ method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
*/
bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index, int type, int *types)
+ const QObject *receiver, int method_index,
+ const QMetaObject *rmeta, int type, int *types)
{
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
+ int method_offset = rmeta ? rmeta->methodOffset() : 0;
+ QObjectPrivate::StaticMetaCallFunction callFunction =
+ (rmeta && QMetaObjectPrivate::get(rmeta)->revision >= 6 && rmeta->d.extradata)
+ ? reinterpret_cast<const QMetaObjectExtraData *>(rmeta->d.extradata)->static_metacall : 0;
+
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
@@ -3184,8 +3197,10 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
const QObjectPrivate::Connection *c2 =
(*connectionLists)[signal_index].first;
+ int method_index_absolute = method_index + method_offset;
+
while (c2) {
- if (c2->receiver == receiver && c2->method == method_index)
+ if (c2->receiver == receiver && c2->method() == method_index_absolute)
return false;
c2 = c2->nextConnectionList;
}
@@ -3196,10 +3211,12 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
c->sender = s;
c->receiver = r;
- c->method = method_index;
+ c->method_relative = method_index;
+ c->method_offset = method_offset;
c->connectionType = type;
c->argumentTypes = types;
c->nextConnectionList = 0;
+ c->callFunction = callFunction;
QT_TRY {
QObjectPrivate::get(s)->addConnection(signal_index, c);
@@ -3260,7 +3277,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
while (c) {
if (c->receiver
&& (receiver == 0 || (c->receiver == receiver
- && (method_index < 0 || c->method == method_index)))) {
+ && (method_index < 0 || c->method() == method_index)))) {
bool needToUnlock = false;
QMutex *receiverMutex = 0;
if (!receiver) {
@@ -3434,12 +3451,11 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
args[0] = 0; // return value
for (int n = 1; n < nargs; ++n)
args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
- QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method,
- sender,
- signal,
- nargs,
- types,
- args));
+ QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method_offset,
+ c->method_relative,
+ c->callFunction,
+ sender, signal, nargs,
+ types, args));
}
@@ -3478,7 +3494,7 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
argv ? argv : empty_argv);
}
- QThreadData *currentThreadData = QThreadData::current();
+ Qt::HANDLE currentThreadId = QThread::currentThreadId();
QMutexLocker locker(signalSlotLock(sender));
QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
@@ -3489,24 +3505,27 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
return;
}
++connectionLists->inUse;
- if (signal_index >= connectionLists->count()) {
- signal_index = -2; //for "all signals";
- }
+
+
+ const QObjectPrivate::ConnectionList *list;
+ if (signal_index < connectionLists->count())
+ list = &connectionLists->at(signal_index);
+ else
+ list = &connectionLists->allsignals;
do {
- QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
+ QObjectPrivate::Connection *c = list->first;
if (!c) continue;
// We need to check against last here to ensure that signals added
// during the signal emission are not emitted in this emission.
- QObjectPrivate::Connection *last = connectionLists->at(signal_index).last;
+ QObjectPrivate::Connection *last = list->last;
do {
if (!c->receiver)
continue;
QObject * const receiver = c->receiver;
- const int method = c->method;
- const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData;
+ const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId;
// determine if this connection should be sent immediately or
// put into the event queue
@@ -3524,7 +3543,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
receiver->metaObject()->className(), receiver);
}
QSemaphore semaphore;
- QCoreApplication::postEvent(receiver, new QMetaCallEvent(method,
+ QCoreApplication::postEvent(receiver, new QMetaCallEvent(c->method_offset, c->method_relative,
+ c->callFunction,
sender, signal_absolute_index,
0, 0,
argv ? argv : empty_argv,
@@ -3534,6 +3554,7 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
continue;
#endif
}
+
QObjectPrivate::Sender currentSender;
QObjectPrivate::Sender *previousSender = 0;
if (receiverInSameThread) {
@@ -3542,36 +3563,52 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
currentSender.ref = 1;
previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
}
- locker.unlock();
+ const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
+ const int method_relative = c->method_relative;
+ if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
+ //we compare the vtable to make sure we are not in the destructor of the object.
+ locker.unlock();
+ if (qt_signal_spy_callback_set.slot_begin_callback != 0)
+ qt_signal_spy_callback_set.slot_begin_callback(receiver, c->method(), argv ? argv : empty_argv);
- if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
- qt_signal_spy_callback_set.slot_begin_callback(receiver,
- method,
- argv ? argv : empty_argv);
- }
+ callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
-#if defined(QT_NO_EXCEPTIONS)
- metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
-#else
- QT_TRY {
- metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
- } QT_CATCH(...) {
+ if (qt_signal_spy_callback_set.slot_end_callback != 0)
+ qt_signal_spy_callback_set.slot_end_callback(receiver, c->method());
locker.relock();
- if (receiverInSameThread)
- QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+ } else {
+ const int method = method_relative + c->method_offset;
+ locker.unlock();
- --connectionLists->inUse;
- Q_ASSERT(connectionLists->inUse >= 0);
- if (connectionLists->orphaned && !connectionLists->inUse)
- delete connectionLists;
- QT_RETHROW;
- }
+ if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
+ qt_signal_spy_callback_set.slot_begin_callback(receiver,
+ method,
+ argv ? argv : empty_argv);
+ }
+
+#if defined(QT_NO_EXCEPTIONS)
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+#else
+ QT_TRY {
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ } QT_CATCH(...) {
+ locker.relock();
+ if (receiverInSameThread)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned && !connectionLists->inUse)
+ delete connectionLists;
+ QT_RETHROW;
+ }
#endif
- if (qt_signal_spy_callback_set.slot_end_callback != 0)
- qt_signal_spy_callback_set.slot_end_callback(receiver, method);
+ if (qt_signal_spy_callback_set.slot_end_callback != 0)
+ qt_signal_spy_callback_set.slot_end_callback(receiver, method);
- locker.relock();
+ locker.relock();
+ }
if (receiverInSameThread)
QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
@@ -3582,7 +3619,9 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
if (connectionLists->orphaned)
break;
- } while (signal_index >= 0 && (signal_index = -1)); //start over for -1 (all signal)
+ } while (list != &connectionLists->allsignals &&
+ //start over for all signals;
+ ((list = &connectionLists->allsignals), true));
--connectionLists->inUse;
Q_ASSERT(connectionLists->inUse >= 0);
@@ -3870,7 +3909,7 @@ void QObject::dumpObjectInfo()
continue;
}
const QMetaObject *receiverMetaObject = c->receiver->metaObject();
- const QMetaMethod method = receiverMetaObject->method(c->method);
+ const QMetaMethod method = receiverMetaObject->method(c->method());
qDebug(" --> %s::%s %s",
receiverMetaObject->className(),
c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
@@ -3887,7 +3926,7 @@ void QObject::dumpObjectInfo()
if (d->senders) {
for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
- const QMetaMethod slot = metaObject()->method(s->method);
+ const QMetaMethod slot = metaObject()->method(s->method());
qDebug(" <-- %s::%s %s",
s->sender->metaObject()->className(),
s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index c7555be..2711a4b 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -108,19 +108,23 @@ public:
QList<QVariant> propertyValues;
};
+ typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
struct Connection
{
QObject *sender;
QObject *receiver;
- int method;
- uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
- QBasicAtomicPointer<int> argumentTypes;
+ StaticMetaCallFunction callFunction;
// The next pointer for the singly-linked ConnectionList
Connection *nextConnectionList;
//senders linked list
Connection *next;
Connection **prev;
+ QBasicAtomicPointer<int> argumentTypes;
+ ushort method_offset;
+ ushort method_relative;
+ ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
~Connection();
+ int method() const { return method_offset + method_relative; }
};
// ConnectionList is a singly-linked list
struct ConnectionList {
@@ -253,25 +257,27 @@ class QSemaphore;
class Q_CORE_EXPORT QMetaCallEvent : public QEvent
{
public:
- QMetaCallEvent(int id, const QObject *sender, int signalId,
+ QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
~QMetaCallEvent();
- inline int id() const { return id_; }
+ inline int id() const { return method_offset_ + method_relative_; }
inline const QObject *sender() const { return sender_; }
inline int signalId() const { return signalId_; }
inline void **args() const { return args_; }
- virtual int placeMetaCall(QObject *object);
+ virtual void placeMetaCall(QObject *object);
private:
- int id_;
const QObject *sender_;
int signalId_;
int nargs_;
int *types_;
void **args_;
QSemaphore *semaphore_;
+ QObjectPrivate::StaticMetaCallFunction callFunction_;
+ ushort method_offset_;
+ ushort method_relative_;
};
class QBoolBlocker
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 54b5ab2..4384837 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -55,7 +55,7 @@ class QByteArray;
class QString;
#ifndef Q_MOC_OUTPUT_REVISION
-#define Q_MOC_OUTPUT_REVISION 62
+#define Q_MOC_OUTPUT_REVISION 63
#endif
// The following macros are our "extensions" to C++
@@ -163,7 +163,10 @@ public: \
virtual void *qt_metacast(const char *); \
QT_TR_FUNCTIONS \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
-private:
+private: \
+ Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; \
+ Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
+
/* tmake ignore Q_OBJECT */
#define Q_OBJECT_FAKE Q_OBJECT
/* tmake ignore Q_GADGET */
@@ -468,7 +471,6 @@ struct Q_CORE_EXPORT QMetaObject
const uint *data;
const void *extradata;
} d;
-
};
typedef const QMetaObject& (*QMetaObjectAccessor)();
@@ -480,7 +482,10 @@ struct QMetaObjectExtraData
#else
const QMetaObject **objects;
#endif
- int (*static_metacall)(QMetaObject::Call, int, void **);
+
+ typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); //from revision 6
+ //typedef int (*StaticMetaCall)(QMetaObject::Call, int, void **); //used from revison 2 until revison 5
+ StaticMetacallFunction static_metacall;
};
inline const char *QMetaObject::className() const
diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp
index 7d63088..73f695b 100644
--- a/src/corelib/kernel/qpointer.cpp
+++ b/src/corelib/kernel/qpointer.cpp
@@ -183,6 +183,7 @@
/*!
\fn bool operator==(const T *o, const QPointer<T> &p)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -191,6 +192,7 @@
*/
/*!
\fn bool operator==(const QPointer<T> &p, const T *o)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -199,6 +201,7 @@
*/
/*!
\fn bool operator==(T *o, const QPointer<T> &p)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -207,6 +210,7 @@
*/
/*!
\fn bool operator==(const QPointer<T> &p, T *o)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -215,6 +219,7 @@
*/
/*!
\fn bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
Equality operator. Returns true if the guarded pointers \a p1 and \a p2
are pointing to the same object, otherwise
@@ -225,6 +230,7 @@
/*!
\fn bool operator!=(const T *o, const QPointer<T> &p)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -232,6 +238,7 @@
*/
/*!
\fn bool operator!=(const QPointer<T> &p, const T *o)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -239,6 +246,7 @@
*/
/*!
\fn bool operator!=(T *o, const QPointer<T> &p)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -246,6 +254,7 @@
*/
/*!
\fn bool operator!=(const QPointer<T> &p, T *o)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -253,6 +262,7 @@
*/
/*!
\fn bool operator!=(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
Inequality operator. Returns true if the guarded pointers \a p1 and
\a p2 are not pointing to the same object, otherwise
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
index 3381afa..18622c7 100644
--- a/src/corelib/kernel/qsystemerror.cpp
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -154,7 +154,7 @@ static QString symbianErrorString(int errorCode)
case KErrInUse:
return QLatin1String("in use");
case KErrNotReady:
- return QLatin1String("not ready (e.g. FS dismounted, no memory card)");
+ return QLatin1String("not ready (e.g. FS dismounted, network down)");
case KErrCorrupt:
return QLatin1String("corrupt");
case KErrAccessDenied:
@@ -190,7 +190,7 @@ static QString symbianErrorString(int errorCode)
case KErrPermissionDenied:
return QLatin1String("permission denied");
default:
- return QString(QLatin1String("symbian error %d")).arg(errorCode);
+ return QString(QLatin1String("symbian error %1")).arg(errorCode);
}
}
#endif
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
index a68abd3..55b65b7 100644
--- a/src/corelib/kernel/qsystemsemaphore_unix.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp
@@ -64,13 +64,6 @@
QT_BEGIN_NAMESPACE
-// We have to define this as on some sem.h will have it
-union qt_semun {
- int val; /* value for SETVAL */
- struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* array for GETALL, SETALL */
-};
-
QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
semaphore(-1), createdFile(false),
createdSemaphore(false), unix_key(-1), error(QSystemSemaphore::NoError)
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 3570564..22b06a5 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -47,6 +47,7 @@
#include "qfileinfo.h"
#include "qstring.h"
+#include "qstringlist.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
#include "qdatastream.h"
@@ -55,6 +56,7 @@
#include "qalgorithms.h"
#include "qhash.h"
#include "qtranslator_p.h"
+#include "qlocale.h"
#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_INTEGRITY)
#define QT_USE_MMAP
@@ -236,6 +238,7 @@ public:
uint contextLength;
uint numerusRulesLength;
+ bool do_load(const QString &filename);
bool do_load(const uchar *data, int len);
QString do_translate(const char *context, const char *sourceText, const char *comment,
int n) const;
@@ -440,7 +443,12 @@ bool QTranslator::load(const QString & filename, const QString & directory,
}
// realname is now the fully qualified name of a readable file.
+ return d->do_load(realname);
+}
+bool QTranslatorPrivate::do_load(const QString &realname)
+{
+ QTranslatorPrivate *d = this;
bool ok = false;
#ifdef QT_USE_MMAP
@@ -502,6 +510,148 @@ bool QTranslator::load(const QString & filename, const QString & directory,
return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
}
+static QString find_translation(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ QString path;
+ if (QFileInfo(filename).isRelative()) {
+ path = directory;
+ if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ }
+
+ QFileInfo fi;
+ QString realname;
+ QStringList fuzzyLocales;
+
+ // see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration
+
+ QStringList languages = locale.uiLanguages();
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ for (int i = languages.size()-1; i >= 0; --i) {
+ QString lang = languages.at(i);
+ QString lowerLang = lang.toLower();
+ if (lang != lowerLang)
+ languages.insert(i+1, lowerLang);
+ }
+#endif
+
+ // try explicit locales names first
+ foreach (QString localeName, languages) {
+ localeName.replace(QLatin1Char('-'), QLatin1Char('_'));
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ fuzzyLocales.append(localeName);
+ }
+
+ // start guessing
+ foreach (QString localeName, fuzzyLocales) {
+ for (;;) {
+ int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
+ // no truncations? fail
+ if (rightmost <= 0)
+ break;
+ localeName.truncate(rightmost);
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+ }
+
+ if (!suffix.isNull()) {
+ realname = path + filename + suffix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+
+ realname = path + filename + prefix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ return QString();
+}
+
+/*!
+ \since 4.8
+
+ Loads \a filename + \a prefix + \a \l{QLocale::uiLanguages()}{ui language
+ name} + \a suffix (".qm" if the \a suffix is not specified), which may be
+ an absolute file name or relative to \a directory. Returns true if the
+ translation is successfully loaded; otherwise returns false.
+
+ The previous contents of this translator object are discarded.
+
+ If the file name does not exist, other file names are tried
+ in the following order:
+
+ \list 1
+ \o File name without \a suffix appended.
+ \o File name with ui language part after a "_" character stripped and \a suffix.
+ \o File name with ui language part stripped without \a suffix appended.
+ \o File name with ui language part stripped further, etc.
+ \endlist
+
+ For example, an application running in the locale with the following
+ l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call
+ load(QLocale::system(), "foo", ".", "/opt/foolib", ".qm"). load() would
+ replace '-' (dash) with '_' (underscore) in the ui language and then try to
+ open the first existing readable file from this list:
+
+ \list 1
+ \o \c /opt/foolib/foo.es.qm
+ \o \c /opt/foolib/foo.es
+ \o \c /opt/foolib/foo.fr_CA.qm
+ \o \c /opt/foolib/foo.fr_CA
+ \o \c /opt/foolib/foo.de.qm
+ \o \c /opt/foolib/foo.de
+ \o \c /opt/foolib/foo.fr.qm
+ \o \c /opt/foolib/foo.fr
+ \o \c /opt/foolib/foo.qm
+ \o \c /opt/foolib/foo.
+ \o \c /opt/foolib/foo
+ \endlist
+
+ For OSs where file system is case sensitive, QTranslator also tries to load
+ a lower-cased version of the locale name.
+*/
+bool QTranslator::load(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ Q_D(QTranslator);
+ d->clear();
+ QString fname = find_translation(locale, filename, prefix, directory, suffix);
+ return !fname.isEmpty() && d->do_load(fname);
+}
+
/*!
\overload load()
\fn bool QTranslator::load(const uchar *data, int len)
@@ -692,7 +842,7 @@ QString QTranslatorPrivate::do_translate(const char *context, const char *source
numerus = numerusHelper(n, numerusRulesArray, numerusRulesLength);
for (;;) {
- quint32 h = elfHash(QByteArray(sourceText) + comment);
+ quint32 h = elfHash(QByteArray(QByteArray(sourceText) + comment).constData());
const uchar *start = offsetArray;
const uchar *end = start + ((numItems-1) << 3);
diff --git a/src/corelib/kernel/qtranslator.h b/src/corelib/kernel/qtranslator.h
index 33e7f03..7a4fa00 100644
--- a/src/corelib/kernel/qtranslator.h
+++ b/src/corelib/kernel/qtranslator.h
@@ -53,6 +53,7 @@ QT_MODULE(Core)
#ifndef QT_NO_TRANSLATION
+class QLocale;
class QTranslatorPrivate;
class Q_CORE_EXPORT QTranslator : public QObject
@@ -77,6 +78,11 @@ public:
const QString & directory = QString(),
const QString & search_delimiters = QString(),
const QString & suffix = QString());
+ bool load(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix = QString(),
+ const QString & directory = QString(),
+ const QString & suffix = QString());
bool load(const uchar *data, int len);
#ifdef QT3_SUPPORT