src/network/kernel/qhostinfo_p.h
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
--- a/src/network/kernel/qhostinfo_p.h	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/network/kernel/qhostinfo_p.h	Tue Feb 02 00:43:10 2010 +0200
@@ -61,17 +61,17 @@
 #include "QtCore/qobject.h"
 #include "QtCore/qpointer.h"
 
-#if !defined QT_NO_THREAD
+#ifndef QT_NO_THREAD
 #include "QtCore/qthread.h"
-#    define QHostInfoAgentBase QThread
-#else
-#    define QHostInfoAgentBase QObject
+#include "QtCore/qthreadpool.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qrunnable.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qqueue.h"
 #endif
 
 QT_BEGIN_NAMESPACE
 
-static const int QHOSTINFO_THREAD_WAIT = 250; // ms
-
 class QHostInfoResult : public QObject
 {
     Q_OBJECT
@@ -79,100 +79,18 @@
     inline void emitResultsReady(const QHostInfo &info)
     {
         emit resultsReady(info);
-        if (autoDelete)
-            delete this;
     }
 
 Q_SIGNALS:
-    void resultsReady(const QHostInfo &info);
-
-public:
-    int lookupId;
-    bool autoDelete;
+    void resultsReady(const QHostInfo info);
 };
 
-struct QHostInfoQuery
-{
-    inline QHostInfoQuery() : object(0) {}
-    inline ~QHostInfoQuery() { delete object; }
-    inline QHostInfoQuery(const QString &name, QHostInfoResult *result)
-        : hostName(name), object(result) {}
-
-    QString hostName;
-    QHostInfoResult *object;
-};
-
-class QHostInfoAgent : public QHostInfoAgentBase
+// needs to be QObject because fromName calls tr()
+class QHostInfoAgent : public QObject
 {
     Q_OBJECT
 public:
-    inline QHostInfoAgent()
-    {
-        // There is a chance that there will be two instances of
-        // QHostInfoAgent if two threads try to get Q_GLOBAL_STATIC
-        // object at the same time. The second object will be deleted
-        // immediately before anyone uses it, but we need to be
-        // careful about what we do in the constructor.
-        static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
-        if (done.testAndSetRelaxed(0, 1))
-            qAddPostRoutine(staticCleanup);
-        moveToThread(QCoreApplicationPrivate::mainThread());
-        quit = false;
-        pendingQueryId = -1;
-    }
-    inline ~QHostInfoAgent()
-    { cleanup(); }
-
-    void run();
     static QHostInfo fromName(const QString &hostName);
-
-    inline void addHostName(const QString &name, QHostInfoResult *result)
-    {
-        QMutexLocker locker(&mutex);
-        queries << new QHostInfoQuery(name, result);
-        cond.wakeOne();
-    }
-
-    inline void abortLookup(int id)
-    {
-        QMutexLocker locker(&mutex);
-        for (int i = 0; i < queries.size(); ++i) {
-            QHostInfoResult *result = queries.at(i)->object;
-            if (result->lookupId == id) {
-                result->disconnect();
-                delete queries.takeAt(i);
-                return;
-            }
-        }
-        if (pendingQueryId == id)
-            pendingQueryId = -1;
-    }
-
-    static void staticCleanup();
-
-public Q_SLOTS:
-    inline void cleanup()
-    {
-        {
-            QMutexLocker locker(&mutex);
-            qDeleteAll(queries);
-            queries.clear();
-            quit = true;
-            cond.wakeOne();
-        }
-#ifndef QT_NO_THREAD
-        if (!wait(QHOSTINFO_THREAD_WAIT))
-            terminate();
-        wait();
-#endif
-    }
-
-private:
-    QList<QHostInfoQuery *> queries;
-    QMutex mutex;
-    QWaitCondition cond;
-    volatile bool quit;
-    int pendingQueryId;
 };
 
 class QHostInfoPrivate
@@ -192,6 +110,52 @@
     int lookupId;
 };
 
+#ifndef QT_NO_THREAD
+// the following classes are used for the (normal) case: We use multiple threads to lookup DNS
+
+class QHostInfoRunnable : public QRunnable
+{
+public:
+    QHostInfoRunnable (QString hn, int i);
+    void run();
+
+    QString toBeLookedUp;
+    int id;
+    QHostInfoResult resultEmitter;
+};
+
+class QHostInfoLookupManager : public QObject
+{
+    Q_OBJECT
+public:
+    QHostInfoLookupManager();
+    ~QHostInfoLookupManager();
+
+    void work();
+
+    // called from QHostInfo
+    void scheduleLookup(QHostInfoRunnable *r);
+    void abortLookup(int id);
+
+    // called from QHostInfoRunnable
+    void lookupFinished(QHostInfoRunnable *r);
+    bool wasAborted(int id);
+
+protected:
+    QList<QHostInfoRunnable*> currentLookups; // in progress
+    QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
+    QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
+    QList<QHostInfoRunnable*> finishedLookups; // recently finished
+    QList<int> abortedLookups; // ids of aborted lookups
+
+    QThreadPool threadPool;
+
+    QMutex mutex;
+
+    bool wasDeleted;
+};
+#endif
+
 QT_END_NAMESPACE
 
 #endif // QHOSTINFO_P_H