lookuphost.cpp
1 //------------------------------------------------------------------------------
2 // lookuphost.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2015 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "lookuphost.h"
24 
25 #include <QHostInfo>
26 #include <QMutex>
27 #include <QMutexLocker>
28 #include <QTimer>
29 #include "log.h"
30 
31 LookupHost *LookupHost::inst = NULL;
32 
33 DClass<LookupHost>
34 {
35 public:
40  static const int MAX_LOOKUPS = 20;
41 
42  QAtomicInt workCounter;
43  int runningLookups;
45  QMutex lock;
46  bool accepting;
47 };
48 
49 DPointeredNoCopy(LookupHost)
50 
52 {
53  d->accepting = true;
54  d->runningLookups = 0;
55 }
56 
57 LookupHost::~LookupHost()
58 {
59 }
60 
61 void LookupHost::lookupHost(const QString &name, QObject *receiver, const char *receiverSlot)
62 {
63  instance()->lookupHost_(name, receiver, receiverSlot);
64 }
65 
66 void LookupHost::lookupHost_(const QString &name, QObject *receiver, const char *receiverSlot)
67 {
68  QMutexLocker locker(&d->lock);
69  if (!d->accepting)
70  {
71  return;
72  }
73  d->workCounter.ref();
74 
75  QTimer *timer = new QTimer();
76  LookupHostWorker *worker = new LookupHostWorker(name);
77 
78  QObject::connect(worker, SIGNAL(hostFound(QHostInfo)), receiver, receiverSlot);
79  worker->connect(timer, SIGNAL(timeout()), SLOT(work()));
80  timer->connect(timer, SIGNAL(timeout()), SLOT(deleteLater()));
81 
82  timer->start(0);
83 
84  worker->moveToThread(&d->thread);
85  timer->moveToThread(&d->thread);
86 }
87 
88 void LookupHost::finalizeAndJoin()
89 {
90  if (inst != NULL)
91  {
92  gLog << tr("Finalizing LookupHost thread");
93  instance()->finalizeAndJoin_();
94  gLog << tr("Finalized LookupHost thread");
95  }
96 }
97 
98 void LookupHost::finalizeAndJoin_()
99 {
100  {
101  QMutexLocker locker(&d->lock);
102  d->accepting = false;
103  }
104  while (d->workCounter > 0)
105  {
106  d->thread.wait(1000);
107  }
108  d->thread.quit();
109 }
110 
111 void LookupHost::derefWorkCounter()
112 {
113  d->workCounter.deref();
114 }
115 
116 LookupHost *LookupHost::instance()
117 {
118  if (inst == NULL)
119  {
120  inst = new LookupHost();
121  inst->d->thread.start();
122  }
123  return inst;
124 }
126 LookupHostWorker::LookupHostWorker(const QString &hostName)
127 {
128  this->hostName = hostName;
129 }
130 
131 void LookupHostWorker::work()
132 {
133  QMutexLocker locker(&LookupHost::instance()->d->lock);
134  if (LookupHost::instance()->d->accepting)
135  {
136  if (LookupHost::instance()->d->runningLookups < PrivData<LookupHost>::MAX_LOOKUPS)
137  {
138  ++LookupHost::instance()->d->runningLookups;
139  QHostInfo::lookupHost(hostName, this, SLOT(hostFoundReceived(QHostInfo)));
140  }
141  else
142  {
143  // Wait a while and try again.
144  QTimer::singleShot(1000, this, SLOT(work()));
145  }
146  }
147  else
148  {
149  LookupHost::instance()->derefWorkCounter();
150  deleteLater();
151  }
152 }
153 
154 void LookupHostWorker::hostFoundReceived(const QHostInfo &hostInfo)
155 {
156  QMutexLocker locker(&LookupHost::instance()->d->lock);
157  --LookupHost::instance()->d->runningLookups;
158  LookupHost::instance()->derefWorkCounter();
159  emit hostFound(hostInfo);
160  deleteLater();
161 }
163 void LookupHostConsumerThread::run()
164 {
165  qDebug() << "LookupHostConsumerThread:" << QThread::currentThreadId();
166  exec();
167 }
Definition: dptr.h:31