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

KDECore

kresolvermanager.cpp

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

KDECore

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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