kdecore Library API Documentation

kresolvermanager.cpp

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