• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

k3resolvermanager.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003-2005 Thiago Macieira <thiago@kde.org>
00003  *
00004  *
00005  *  Permission is hereby granted, free of charge, to any person obtaining
00006  *  a copy of this software and associated documentation files (the
00007  *  "Software"), to deal in the Software without restriction, including
00008  *  without limitation the rights to use, copy, modify, merge, publish,
00009  *  distribute, sublicense, and/or sell copies of the Software, and to
00010  *  permit persons to whom the Software is furnished to do so, subject to
00011  *  the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be included
00014  *  in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #include <config.h>
00026 #include <config-network.h>
00027 
00028 #include <sys/types.h>
00029 #include <netinet/in.h>
00030 #include <limits.h>
00031 #include <unistd.h>     // only needed for pid_t
00032 
00033 #ifdef HAVE_RES_INIT
00034 # include <sys/stat.h>
00035 extern "C" {
00036 #   include <arpa/nameser.h>
00037 }
00038 # include <time.h>
00039 # include <resolv.h>
00040 #endif
00041 
00042 #include <QByteArray>
00043 #include <QCoreApplication>
00044 #include <QList>
00045 #include <QMutableListIterator>
00046 #include <QMutex>
00047 #include <QQueue>
00048 #include <QSemaphore>
00049 
00050 #include <QThread>
00051 #include <QTimer>
00052 #include <QWaitCondition>
00053 
00054 #include <kde_file.h>
00055 #include <kdebug.h>
00056 #include "k3resolver.h"
00057 #include "k3resolver_p.h"
00058 #include "k3resolverworkerbase.h"
00059 #include "k3resolverstandardworkers_p.h"
00060 
00061 using namespace KNetwork;
00062 using namespace KNetwork::Internal;
00063 
00064 /*
00065  * Explanation on how the resolver system works
00066 
00067    When KResolver::start is called, it calls KResolverManager::enqueue to add
00068    an entry to the queue. KResolverManager::enqueue will verify the availability
00069    of a worker thread: if one is available, it will dispatch the request to it.
00070    If no threads are available, it will then decide whether to launch a thread
00071    or to queue for the future.
00072 
00073    (This process is achieved by always queuing the new request, starting a
00074    new thread if necessary and then notifying of the availability of data
00075    to all worker threads).
00076 
00077  * Worker thread
00078    A new thread, when started, will enter its event loop
00079    immediately. That is, it'll first try to acquire new data to
00080    process, which means it will lock and unlock the manager mutex in
00081    the process.
00082 
00083    If it finds no new data, it'll wait on the feedWorkers condition
00084    for a certain maximum time. If that time expires and there's still
00085    no data, the thread will exit, in order to save system resources.
00086 
00087    If it finds data, however, it'll set up and call the worker class
00088    that has been selected by the manager. Once that worker is done,
00089    the thread releases the data through KResolverManager::releaseData.
00090 
00091  * Data requesting/releasing
00092    A worker thread always calls upon functions on the resolver manager
00093    in order to acquire and release data.
00094 
00095    When data is being requested, the KResolverManager::requestData
00096    function will look the currentRequests list and return the first
00097    Queued request it finds, while marking it to be InProgress.
00098 
00099    When the worker class has returned, the worker thread will release
00100    that data through the KResolverManager::releaseData function. If the
00101    worker class has requested no further data (nRequests == 0), the
00102    request's status is marked to be Done. It'll then look at the
00103    requestor for that data: if it was requested by another worker,
00104    it'll decrement the requests count for that one and add the results
00105    to a list. And, finally, if the requests count for the requestor
00106    becomes 0, it'll repeat this process for the requestor as well
00107    (change status to Done, check for a requestor).
00108  */
00109 
00110 namespace
00111 {
00112 
00113 /*
00114  * This class is used to control the access to the
00115  * system's resolver API.
00116  *
00117  * It is necessary to periodically poll /etc/resolv.conf and reload
00118  * it if any changes are noticed. This class does exactly that.
00119  *
00120  * However, there's also the problem of reloading the structure while
00121  * some threads are in progress. Therefore, we keep a usage reference count.
00122  */
00123 class ResInitUsage
00124 {
00125 public:
00126 
00127 #ifdef HAVE_RES_INIT
00128   time_t mTime;
00129   int useCount;
00130 
00131 # ifndef RES_INIT_THREADSAFE
00132   QWaitCondition cond;
00133   QMutex mutex;
00134 # endif
00135 
00136   bool shouldResInit()
00137   {
00138     // check if /etc/resolv.conf has changed
00139     KDE_struct_stat st;
00140     if (KDE_stat("/etc/resolv.conf", &st) != 0)
00141       return false;
00142 
00143     if (mTime != st.st_mtime)
00144       {
00145     kDebug(179) << "shouldResInit: /etc/resolv.conf updated";
00146     return true;
00147       }
00148     return false;
00149   }
00150 
00151   void callResInit()
00152   {
00153     if (mTime != 0)
00154       {
00155     // don't call it the first time
00156     // let it be initialized naturally
00157     kDebug(179) << "callResInit: calling res_init()";
00158     res_init();
00159       }
00160 
00161     KDE_struct_stat st;
00162     if (KDE_stat("/etc/resolv.conf", &st) == 0)
00163       mTime = st.st_mtime;
00164   }
00165 
00166   ResInitUsage()
00167     : mTime(0), useCount(0)
00168   { }
00169 
00170   /*
00171    * Marks the end of usage to the resolver tools
00172    */
00173   void release()
00174   {
00175 # ifndef RES_INIT_THREADSAFE
00176     QMutexLocker locker(&mutex);
00177     if (--useCount == 0)
00178       {
00179     if (shouldResInit())
00180       callResInit();
00181 
00182     // we've reached 0, wake up anyone that's waiting to call res_init
00183     cond.wakeAll();
00184       }
00185 # else
00186     // do nothing
00187 # endif
00188   }
00189 
00190   /*
00191    * Marks the beginning of usage of the resolver API
00192    */
00193   void acquire()
00194   {
00195 # ifndef RES_INIT_THREADSAFE
00196     mutex.lock();
00197 
00198     if (shouldResInit())
00199       {
00200     if (useCount)
00201       {
00202         // other threads are already using the API, so wait till
00203         // it's all clear
00204         // the thread that emits this condition will also call res_init
00205         //qDebug("ResInitUsage: waiting for libresolv to be clear");
00206         cond.wait(&mutex);
00207       }
00208     else
00209       // we're clear
00210       callResInit();
00211       }
00212     useCount++;
00213     mutex.unlock();
00214 
00215 # else
00216     if (shouldResInit())
00217       callResInit();
00218 
00219 # endif
00220   }
00221 
00222 #else
00223   ResInitUsage()
00224   { }
00225 
00226   bool shouldResInit()
00227   { return false; }
00228 
00229   void acquire()
00230   { }
00231 
00232   void release()
00233   { }
00234 #endif
00235 
00236 } resInit;
00237 
00238 } // anonymous namespace
00239 
00240 /*
00241  * parameters
00242  */
00243 // a thread will try maxThreadRetries to get data, waiting at most
00244 // maxThreadWaitTime milliseconds between each attempt. After that, it'll
00245 // exit
00246 static const int maxThreadWaitTime = 2000; // 2 seconds
00247 static const int maxThreads = 5;
00248 
00249 static pid_t pid;       // FIXME -- disable when everything is ok
00250 
00251 KResolverThread::KResolverThread()
00252   : data(0L)
00253 {
00254 }
00255 
00256 // remember! This function runs in a separate thread!
00257 void KResolverThread::run()
00258 {
00259   // initialization
00260   // enter the loop already
00261 
00262   //qDebug("KResolverThread(thread %u/%p): started", pid, (void*)QThread::currentThread());
00263   KResolverManager::manager()->registerThread(this);
00264   while (true)
00265     {
00266       data = KResolverManager::manager()->requestData(this, ::maxThreadWaitTime);
00267       //qDebug("KResolverThread(thread %u/%p) got data %p", KResolverManager::pid,
00268       //       (void*)QThread::currentThread(), (void*)data);
00269       if (data)
00270     {
00271       // yes, we got data
00272       // process it!
00273 
00274       // 1) set up
00275       ;
00276 
00277       // 2) run it
00278       data->worker->run();
00279 
00280       // 3) release data
00281       KResolverManager::manager()->releaseData(this, data);
00282 
00283       // now go back to the loop
00284     }
00285       else
00286     break;
00287     }
00288 
00289   KResolverManager::manager()->unregisterThread(this);
00290   //qDebug("KResolverThread(thread %u/%p): exiting", pid, (void*)QThread::currentThread());
00291 }
00292 
00293 bool KResolverThread::checkResolver()
00294 {
00295   return resInit.shouldResInit();
00296 }
00297 
00298 void KResolverThread::acquireResolver()
00299 {
00300 #if defined(NEED_MUTEX) && !defined(Q_OS_FREEBSD)
00301   getXXbyYYmutex.lock();
00302 #endif
00303 
00304   resInit.acquire();
00305 }
00306 
00307 void KResolverThread::releaseResolver()
00308 {
00309 #if defined(NEED_MUTEX) && !defined(Q_OS_FREEBSD)
00310   getXXbyYYmutex.unlock();
00311 #endif
00312 
00313   resInit.release();
00314 }
00315 
00316 static KResolverManager *globalManager;
00317 
00318 KResolverManager* KResolverManager::manager()
00319 {
00320   if (globalManager == 0L)
00321     new KResolverManager();
00322   return globalManager;
00323 }
00324 
00325 KResolverManager::KResolverManager()
00326   : runningThreads(0), availableThreads(0)
00327 {
00328   globalManager = this;
00329   initStandardWorkers();
00330 
00331   pid = getpid();
00332 }
00333 
00334 KResolverManager::~KResolverManager()
00335 {
00336   // this should never be called
00337 
00338   // kill off running threads
00339   foreach (KResolverThread* worker, workers)
00340     worker->terminate();
00341 }
00342 
00343 void KResolverManager::registerThread(KResolverThread* )
00344 {
00345 }
00346 
00347 void KResolverManager::unregisterThread(KResolverThread*)
00348 {
00349   runningThreads--;
00350 }
00351 
00352 // this function is called by KResolverThread::run
00353 RequestData* KResolverManager::requestData(KResolverThread *th, int maxWaitTime)
00354 {
00356   // This function is called in a worker thread!!
00358 
00359   // lock the mutex, so that the manager thread or other threads won't
00360   // interfere.
00361   QMutexLocker locker(&mutex);
00362   RequestData *data = findData(th);
00363 
00364   if (data)
00365     // it found something, that's good
00366     return data;
00367 
00368   // nope, nothing found; sleep for a while
00369   availableThreads++;
00370   feedWorkers.wait(&mutex, maxWaitTime);
00371   availableThreads--;
00372 
00373   data = findData(th);
00374   return data;
00375 }
00376 
00377 RequestData* KResolverManager::findData(KResolverThread* th)
00378 {
00380   // This function is called by requestData() above and must
00381   // always be called with a locked mutex
00383 
00384   // now find data to be processed
00385   QMutableListIterator<RequestData*> it(newRequests);
00386   while (it.hasNext())
00387     {
00388       RequestData *curr = it.next();
00389       if (!curr->worker->m_finished)
00390     {
00391       // found one
00392       if (curr->obj)
00393         curr->obj->status = KResolver::InProgress;
00394       curr->worker->th = th;
00395 
00396       // move it to the currentRequests list
00397       it.remove();
00398       currentRequests.append(curr);
00399 
00400       return curr;
00401     }
00402     }
00403 
00404   // found nothing!
00405   return 0L;
00406 }
00407 
00408 // this function is called by KResolverThread::run
00409 void KResolverManager::releaseData(KResolverThread *, RequestData* data)
00410 {
00412   // This function is called in a worker thread!!
00414 
00415   //qDebug("KResolverManager::releaseData(%u/%p): %p has been released", pid,
00416 //   (void*)QThread::currentThread(), (void*)data);
00417 
00418   if (data->obj)
00419     {
00420       data->obj->status = KResolver::PostProcessing;
00421     }
00422 
00423   data->worker->m_finished = true;
00424   data->worker->th = 0L;    // this releases the object
00425 
00426   // handle finished requests
00427   handleFinished();
00428 }
00429 
00430 // this function is called by KResolverManager::releaseData above
00431 void KResolverManager::handleFinished()
00432 {
00433   bool redo = false;
00434   QQueue<RequestData*> doneRequests;
00435 
00436   mutex.lock();
00437   if (currentRequests.isEmpty())
00438     {
00439       mutex.unlock();
00440       return;
00441     }
00442 
00443   // loop over all items on the currently running list
00444   // we loop from the last to the first so that we catch requests
00445   // with "requestors" before we catch the requestor itself.
00446   QMutableListIterator<RequestData*> it(currentRequests);
00447   it.toBack();
00448   while (it.hasPrevious())
00449     {
00450       RequestData *curr = it.previous();
00451       if (curr->worker->th == 0L)
00452     {
00453       if (handleFinishedItem(curr))
00454         {
00455           it.remove();
00456           doneRequests.enqueue(curr);
00457 
00458           if (curr->requestor &&
00459           curr->requestor->nRequests == 0 &&
00460           curr->requestor->worker->m_finished)
00461         // there's a requestor that is now finished
00462         redo = true;
00463         }
00464     }
00465     }
00466 
00467   //qDebug("KResolverManager::handleFinished(%u): %d requests to notify", pid, doneRequests.count());
00468   while (!doneRequests.isEmpty())
00469     doNotifying(doneRequests.dequeue());
00470 
00471   mutex.unlock();
00472 
00473   if (redo)
00474     {
00475       //qDebug("KResolverManager::handleFinished(%u): restarting processing to catch requestor",
00476     //     pid);
00477       handleFinished();
00478     }
00479 }
00480 
00481 // This function is called by KResolverManager::handleFinished above
00482 bool KResolverManager::handleFinishedItem(RequestData* curr)
00483 
00484 {
00485   // for all items that aren't currently running, remove from the list
00486   // this includes all finished or canceled requests
00487 
00488   if (curr->worker->m_finished && curr->nRequests == 0)
00489     {
00490       // this one has finished
00491       if (curr->obj)
00492     curr->obj->status = KResolver::PostProcessing; // post-processing is run in doNotifying()
00493 
00494       if (curr->requestor)
00495     --curr->requestor->nRequests;
00496 
00497       //qDebug("KResolverManager::handleFinishedItem(%u): removing %p since it's done",
00498     //     pid, (void*)curr);
00499       return true;
00500     }
00501   return false;
00502 }
00503 
00504 
00505 
00506 void KResolverManager::registerNewWorker(KResolverWorkerFactoryBase *factory)
00507 {
00508   workerFactories.append(factory);
00509 }
00510 
00511 KResolverWorkerBase* KResolverManager::findWorker(KResolverPrivate* p)
00512 {
00514   // this function can be called on any user thread
00516 
00517   // this function is called with an unlocked mutex and it's expected to be
00518   // thread-safe!
00519   // but the factory list is expected not to be changed asynchronously
00520 
00521   // This function is responsible for finding a suitable worker for the given
00522   // input. That means we have to do a costly operation to create each worker
00523   // class and call their preprocessing functions. The first one that
00524   // says they can process (i.e., preprocess() returns true) will get the job.
00525 
00526   foreach (KResolverWorkerFactoryBase *factory, workerFactories)
00527     {
00528       KResolverWorkerBase *worker = factory->create();
00529 
00530       // set up the data the worker needs to preprocess
00531       worker->input = &p->input;
00532 
00533       if (worker->preprocess())
00534     {
00535       // good, this one says it can process
00536       if (worker->m_finished)
00537         p->status = KResolver::PostProcessing;
00538       else
00539         p->status = KResolver::Queued;
00540       return worker;
00541     }
00542 
00543       // no, try again
00544       delete worker;
00545     }
00546 
00547   // found no worker
00548   return 0L;
00549 }
00550 
00551 void KResolverManager::doNotifying(RequestData *p)
00552 {
00554   // This function may be called on any thread
00555   // any thread at all: user threads, GUI thread, manager thread or worker thread
00557 
00558   // Notification and finalisation
00559   //
00560   // Once a request has finished the normal processing, we call the
00561   // post processing function.
00562   //
00563   // After that is done, we will consolidate all results in the object's
00564   // KResolverResults and then post an event indicating that the signal
00565   // be emitted
00566   //
00567   // In case we detect that the object is waiting for completion, we do not
00568   // post the event, for KResolver::wait will take care of emitting the
00569   // signal.
00570   //
00571   // Once we release the mutex on the object, we may no longer reference it
00572   // for it might have been deleted.
00573 
00574   // "User" objects are those that are not created by the manager. Note that
00575   // objects created by worker threads are considered "user" objects. Objects
00576   // created by the manager are those created for KResolver::resolveAsync.
00577   // We should delete them.
00578 
00579   if (p->obj)
00580     {
00581       // lock the object
00582       p->obj->mutex.lock();
00583       KResolver* parent = p->obj->parent; // is 0 for non-"user" objects
00584       KResolverResults& r = p->obj->results;
00585 
00586       if (p->obj->status == KResolver::Canceled)
00587     {
00588       p->obj->status = KResolver::Canceled;
00589       p->obj->errorcode = KResolver::Canceled;
00590       p->obj->syserror = 0;
00591       r.setError(KResolver::Canceled, 0);
00592     }
00593       else if (p->worker)
00594     {
00595       // post processing
00596       p->worker->postprocess(); // ignore the result
00597 
00598       // copy the results from the worker thread to the final
00599       // object
00600       r = p->worker->results;
00601 
00602       // reset address
00603       r.setAddress(p->input->node, p->input->service);
00604 
00605       //qDebug("KResolverManager::doNotifying(%u/%p): for %p whose status is %d and has %d results",
00606          //pid, (void*)QThread::currentThread(), (void*)p, p->obj->status, r.count());
00607 
00608       p->obj->errorcode = r.error();
00609       p->obj->syserror = r.systemError();
00610       p->obj->status = !r.isEmpty() ?
00611         KResolver::Success : KResolver::Failed;
00612     }
00613       else
00614     {
00615       r.empty();
00616       r.setError(p->obj->errorcode, p->obj->syserror);
00617     }
00618 
00619       // check whether there's someone waiting
00620       if (!p->obj->waiting && parent)
00621     // no, so we must post an event requesting that the signal be emitted
00622     // sorry for the C-style cast, but neither static nor reintepret cast work
00623     // here; I'd have to do two casts
00624     QCoreApplication::postEvent(parent, new QEvent((QEvent::Type)(ResolutionCompleted)));
00625 
00626       // release the mutex
00627       p->obj->mutex.unlock();
00628     }
00629   else
00630     {
00631       // there's no object!
00632       if (p->worker)
00633     p->worker->postprocess();
00634     }
00635 
00636   delete p->worker;
00637 
00638   // ignore p->requestor and p->nRequests
00639   // they have been dealt with by the main loop
00640 
00641   delete p;
00642 
00643   // notify any objects waiting in KResolver::wait
00644   notifyWaiters.wakeAll();
00645 }
00646 
00647 // enqueue a new request
00648 // this function is called from KResolver::start and
00649 // from KResolverWorkerBase::enqueue
00650 void KResolverManager::enqueue(KResolver *obj, RequestData *requestor)
00651 {
00652   RequestData *newrequest = new RequestData;
00653   newrequest->nRequests = 0;
00654   newrequest->obj = obj->d;
00655   newrequest->input = &obj->d->input;
00656   newrequest->requestor = requestor;
00657 
00658   // when processing a new request, find the most
00659   // suitable worker
00660   if ((newrequest->worker = findWorker(obj->d)) == 0L)
00661     {
00662       // oops, problem
00663       // cannot find a worker class for this guy
00664       obj->d->status = KResolver::Failed;
00665       obj->d->errorcode = KResolver::UnsupportedFamily;
00666       obj->d->syserror = 0;
00667 
00668       doNotifying(newrequest);
00669       return;
00670     }
00671 
00672   // no, queue it
00673   // p->status was set in findWorker!
00674   if (requestor)
00675     requestor->nRequests++;
00676 
00677   if (!newrequest->worker->m_finished)
00678     dispatch(newrequest);
00679   else if (newrequest->nRequests > 0)
00680     {
00681       mutex.lock();
00682       currentRequests.append(newrequest);
00683       mutex.unlock();
00684     }
00685   else
00686     // already done
00687     doNotifying(newrequest);
00688 }
00689 
00690 // a new request has been created
00691 // dispatch it
00692 void KResolverManager::dispatch(RequestData *data)
00693 {
00694   // As stated in the beginning of the file, this function
00695   // is supposed to verify the availability of threads, start
00696   // any if necessary
00697 
00698   QMutexLocker locker(&mutex);
00699 
00700   // add to the queue
00701   newRequests.append(data);
00702 
00703   // check if we need to start a new thread
00704   //
00705   // we depend on the variables availableThreads and runningThreads to
00706   // know if we are supposed to start any threads:
00707   // - if availableThreads > 0, then there is at least one thread waiting,
00708   //    blocked in KResolverManager::requestData. It can't unblock
00709   //    while we are holding the mutex locked, therefore we are sure that
00710   //    our event will be handled
00711   // - if availableThreads == 0:
00712   //   - if runningThreads < maxThreads
00713   //     we will start a new thread, which will certainly block in
00714   //     KResolverManager::requestData because we are holding the mutex locked
00715   //   - if runningThreads == maxThreads
00716   //     This situation generally means that we have already maxThreads running
00717   //     and that all of them are processing. We will not start any new threads,
00718   //     but will instead wait for one to finish processing and request new data
00719   //
00720   //     There's a possible race condition here, which goes unhandled: if one of
00721   //     threads has timed out waiting for new data and is in the process of
00722   //     exiting. In that case, availableThreads == 0 and runningThreads will not
00723   //     have decremented yet. This means that we will not start a new thread
00724   //     that we could have. However, since there are other threads working, our
00725   //     event should be handled soon.
00726   //     It won't be handled if and only if ALL threads are in the process of
00727   //     exiting. That situation is EXTREMELY unlikely and is not handled either.
00728   //
00729   if (availableThreads == 0 && runningThreads < maxThreads)
00730     {
00731       // yes, a new thread should be started
00732 
00733       // find if there's a finished one
00734       KResolverThread *th = 0L;
00735       for (int i = 0; i < workers.size(); ++i)
00736     if (!workers[i]->isRunning())
00737       {
00738         th = workers[i];
00739         break;
00740       }
00741 
00742       if (th == 0L)
00743     {
00744       // no, create one
00745       th = new KResolverThread;
00746       workers.append(th);
00747     }
00748 
00749       th->start();
00750       runningThreads++;
00751     }
00752 
00753   feedWorkers.wakeAll();
00754 
00755   // clean up idle threads
00756   QMutableListIterator<KResolverThread*> it(workers);
00757   while (it.hasNext())
00758     {
00759       KResolverThread *worker = it.next();
00760       if (!worker->isRunning())
00761     {
00762       it.remove();
00763       delete worker;
00764     }
00765     }
00766 }
00767 
00768 // this function is called by KResolverManager::dequeue
00769 bool KResolverManager::dequeueNew(KResolver* obj)
00770 {
00771   // This function must be called with a locked mutex
00772   // Deadlock warning:
00773   // always lock the global mutex first if both mutexes must be locked
00774 
00775   KResolverPrivate *d = obj->d;
00776 
00777   // check if it's in the new request list
00778   for (QMutableListIterator<RequestData*> it(newRequests);
00779        it.hasNext(); )
00780     {
00781       RequestData *curr = it.next();
00782       if (curr->obj == d)
00783     {
00784       // yes, this object is still in the list
00785       // but it has never been processed
00786       d->status = KResolver::Canceled;
00787       d->errorcode = KResolver::Canceled;
00788       d->syserror = 0;
00789       it.remove();
00790 
00791       delete curr->worker;
00792       delete curr;
00793 
00794       return true;
00795     }
00796     }
00797 
00798   // check if it's running
00799   for (int i = 0; i < currentRequests.size(); ++i)
00800     {
00801       RequestData* curr = currentRequests[i];
00802       if (curr->obj == d)
00803     {
00804       // it's running. We cannot simply take it out of the list.
00805       // it will be handled when the thread that is working on it finishes
00806       d->mutex.lock();
00807 
00808       d->status = KResolver::Canceled;
00809       d->errorcode = KResolver::Canceled;
00810       d->syserror = 0;
00811 
00812       // disengage from the running threads
00813       curr->obj = 0L;
00814       curr->input = 0L;
00815       if (curr->worker)
00816         curr->worker->input = 0L;
00817 
00818       d->mutex.unlock();
00819     }
00820     }
00821 
00822   return false;
00823 }
00824 
00825 // this function is called by KResolver::cancel
00826 // it's expected to be thread-safe
00827 void KResolverManager::dequeue(KResolver *obj)
00828 {
00829   QMutexLocker locker(&mutex);
00830   dequeueNew(obj);
00831 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal