src/network/kernel/qhostinfo_p.h
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    59 #include "QtCore/qmutex.h"
    59 #include "QtCore/qmutex.h"
    60 #include "QtCore/qwaitcondition.h"
    60 #include "QtCore/qwaitcondition.h"
    61 #include "QtCore/qobject.h"
    61 #include "QtCore/qobject.h"
    62 #include "QtCore/qpointer.h"
    62 #include "QtCore/qpointer.h"
    63 
    63 
    64 #if !defined QT_NO_THREAD
    64 #ifndef QT_NO_THREAD
    65 #include "QtCore/qthread.h"
    65 #include "QtCore/qthread.h"
    66 #    define QHostInfoAgentBase QThread
    66 #include "QtCore/qthreadpool.h"
    67 #else
    67 #include "QtCore/qmutex.h"
    68 #    define QHostInfoAgentBase QObject
    68 #include "QtCore/qrunnable.h"
       
    69 #include "QtCore/qlist.h"
       
    70 #include "QtCore/qqueue.h"
    69 #endif
    71 #endif
    70 
    72 
    71 QT_BEGIN_NAMESPACE
    73 QT_BEGIN_NAMESPACE
    72 
       
    73 static const int QHOSTINFO_THREAD_WAIT = 250; // ms
       
    74 
    74 
    75 class QHostInfoResult : public QObject
    75 class QHostInfoResult : public QObject
    76 {
    76 {
    77     Q_OBJECT
    77     Q_OBJECT
    78 public Q_SLOTS:
    78 public Q_SLOTS:
    79     inline void emitResultsReady(const QHostInfo &info)
    79     inline void emitResultsReady(const QHostInfo &info)
    80     {
    80     {
    81         emit resultsReady(info);
    81         emit resultsReady(info);
    82         if (autoDelete)
       
    83             delete this;
       
    84     }
    82     }
    85 
    83 
    86 Q_SIGNALS:
    84 Q_SIGNALS:
    87     void resultsReady(const QHostInfo &info);
    85     void resultsReady(const QHostInfo info);
    88 
       
    89 public:
       
    90     int lookupId;
       
    91     bool autoDelete;
       
    92 };
    86 };
    93 
    87 
    94 struct QHostInfoQuery
    88 // needs to be QObject because fromName calls tr()
    95 {
    89 class QHostInfoAgent : public QObject
    96     inline QHostInfoQuery() : object(0) {}
       
    97     inline ~QHostInfoQuery() { delete object; }
       
    98     inline QHostInfoQuery(const QString &name, QHostInfoResult *result)
       
    99         : hostName(name), object(result) {}
       
   100 
       
   101     QString hostName;
       
   102     QHostInfoResult *object;
       
   103 };
       
   104 
       
   105 class QHostInfoAgent : public QHostInfoAgentBase
       
   106 {
    90 {
   107     Q_OBJECT
    91     Q_OBJECT
   108 public:
    92 public:
   109     inline QHostInfoAgent()
       
   110     {
       
   111         // There is a chance that there will be two instances of
       
   112         // QHostInfoAgent if two threads try to get Q_GLOBAL_STATIC
       
   113         // object at the same time. The second object will be deleted
       
   114         // immediately before anyone uses it, but we need to be
       
   115         // careful about what we do in the constructor.
       
   116         static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
       
   117         if (done.testAndSetRelaxed(0, 1))
       
   118             qAddPostRoutine(staticCleanup);
       
   119         moveToThread(QCoreApplicationPrivate::mainThread());
       
   120         quit = false;
       
   121         pendingQueryId = -1;
       
   122     }
       
   123     inline ~QHostInfoAgent()
       
   124     { cleanup(); }
       
   125 
       
   126     void run();
       
   127     static QHostInfo fromName(const QString &hostName);
    93     static QHostInfo fromName(const QString &hostName);
   128 
       
   129     inline void addHostName(const QString &name, QHostInfoResult *result)
       
   130     {
       
   131         QMutexLocker locker(&mutex);
       
   132         queries << new QHostInfoQuery(name, result);
       
   133         cond.wakeOne();
       
   134     }
       
   135 
       
   136     inline void abortLookup(int id)
       
   137     {
       
   138         QMutexLocker locker(&mutex);
       
   139         for (int i = 0; i < queries.size(); ++i) {
       
   140             QHostInfoResult *result = queries.at(i)->object;
       
   141             if (result->lookupId == id) {
       
   142                 result->disconnect();
       
   143                 delete queries.takeAt(i);
       
   144                 return;
       
   145             }
       
   146         }
       
   147         if (pendingQueryId == id)
       
   148             pendingQueryId = -1;
       
   149     }
       
   150 
       
   151     static void staticCleanup();
       
   152 
       
   153 public Q_SLOTS:
       
   154     inline void cleanup()
       
   155     {
       
   156         {
       
   157             QMutexLocker locker(&mutex);
       
   158             qDeleteAll(queries);
       
   159             queries.clear();
       
   160             quit = true;
       
   161             cond.wakeOne();
       
   162         }
       
   163 #ifndef QT_NO_THREAD
       
   164         if (!wait(QHOSTINFO_THREAD_WAIT))
       
   165             terminate();
       
   166         wait();
       
   167 #endif
       
   168     }
       
   169 
       
   170 private:
       
   171     QList<QHostInfoQuery *> queries;
       
   172     QMutex mutex;
       
   173     QWaitCondition cond;
       
   174     volatile bool quit;
       
   175     int pendingQueryId;
       
   176 };
    94 };
   177 
    95 
   178 class QHostInfoPrivate
    96 class QHostInfoPrivate
   179 {
    97 {
   180 public:
    98 public:
   190     QList<QHostAddress> addrs;
   108     QList<QHostAddress> addrs;
   191     QString hostName;
   109     QString hostName;
   192     int lookupId;
   110     int lookupId;
   193 };
   111 };
   194 
   112 
       
   113 #ifndef QT_NO_THREAD
       
   114 // the following classes are used for the (normal) case: We use multiple threads to lookup DNS
       
   115 
       
   116 class QHostInfoRunnable : public QRunnable
       
   117 {
       
   118 public:
       
   119     QHostInfoRunnable (QString hn, int i);
       
   120     void run();
       
   121 
       
   122     QString toBeLookedUp;
       
   123     int id;
       
   124     QHostInfoResult resultEmitter;
       
   125 };
       
   126 
       
   127 class QHostInfoLookupManager : public QObject
       
   128 {
       
   129     Q_OBJECT
       
   130 public:
       
   131     QHostInfoLookupManager();
       
   132     ~QHostInfoLookupManager();
       
   133 
       
   134     void work();
       
   135 
       
   136     // called from QHostInfo
       
   137     void scheduleLookup(QHostInfoRunnable *r);
       
   138     void abortLookup(int id);
       
   139 
       
   140     // called from QHostInfoRunnable
       
   141     void lookupFinished(QHostInfoRunnable *r);
       
   142     bool wasAborted(int id);
       
   143 
       
   144 protected:
       
   145     QList<QHostInfoRunnable*> currentLookups; // in progress
       
   146     QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
       
   147     QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
       
   148     QList<QHostInfoRunnable*> finishedLookups; // recently finished
       
   149     QList<int> abortedLookups; // ids of aborted lookups
       
   150 
       
   151     QThreadPool threadPool;
       
   152 
       
   153     QMutex mutex;
       
   154 
       
   155     bool wasDeleted;
       
   156 };
       
   157 #endif
       
   158 
   195 QT_END_NAMESPACE
   159 QT_END_NAMESPACE
   196 
   160 
   197 #endif // QHOSTINFO_P_H
   161 #endif // QHOSTINFO_P_H