KDECore
k3resolver_p.h
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 #ifndef KRESOLVER_P_H 00026 #define KRESOLVER_P_H 00027 00028 #include <config.h> 00029 #include <config-network.h> 00030 #include <sys/types.h> 00031 00032 00033 #include <QByteArray> 00034 #include <QList> 00035 #include <QThread> 00036 #include <QMutex> 00037 #include <QWaitCondition> 00038 #include <QSemaphore> 00039 #include <QEvent> 00040 00041 #include "k3resolver.h" 00042 00043 /* decide whether we need a mutex */ 00044 #if !defined(HAVE_GETPROTOBYNAME_R) || !defined(HAVE_GETSERVBYNAME_R) || !defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETSERVBYPORT_R) 00045 # define NEED_MUTEX 00046 extern QMutex getXXbyYYmutex; 00047 #endif 00048 00049 /* some systems have the functions, but don't declare them */ 00050 #if defined(HAVE_GETSERVBYNAME_R) && !HAVE_GETSERVBYNAME_R_PROTO 00051 extern "C" { 00052 struct servent; 00053 extern int getservbyname_r(const char* serv, const char* proto, 00054 struct servent* servbuf, 00055 char* buf, size_t buflen, 00056 struct servent** result); 00057 extern int getservbyport_r(int port, const char* proto, 00058 struct servent* servbuf, 00059 char* buf, size_t buflen, 00060 struct servent** result); 00061 00062 struct protoent; 00063 extern int getprotobyname_r(const char* proto, struct protoent* protobuf, 00064 char *buf, size_t buflen, 00065 struct protoent** result); 00066 extern int getprotobynumber_r(int proto, struct protoent* protobuf, 00067 char *buf, size_t buflen, 00068 struct protoent** result); 00069 } 00070 #endif 00071 00072 /* decide whether res_init is thread-safe or not */ 00073 #if defined(__GLIBC__) 00074 # undef RES_INIT_THREADSAFE 00075 #endif 00076 00077 namespace KNetwork 00078 { 00079 // defined in network/qresolverworkerbase.h 00080 class KResolverWorkerBase; 00081 class KResolverWorkerFactoryBase; 00082 class KResolverPrivate; 00083 00084 namespace Internal 00085 { 00086 class KResolverManager; 00087 class KResolverThread; 00088 struct RequestData; 00089 00090 struct InputData 00091 { 00092 QString node, service; 00093 QByteArray protocolName; 00094 int flags; 00095 int familyMask; 00096 int socktype; 00097 int protocol; 00098 }; 00099 } 00100 00101 class KResolverPrivate 00102 { 00103 public: 00104 // parent class. Should never be changed! 00105 KResolver* parent; 00106 bool deleteWhenDone : 1; 00107 bool waiting : 1; 00108 00109 // class status. Should not be changed by worker threads! 00110 volatile int status; 00111 volatile int errorcode, syserror; 00112 00113 // input data. Should not be changed by worker threads! 00114 Internal::InputData input; 00115 00116 // mutex 00117 QMutex mutex; 00118 00119 // output data 00120 KResolverResults results; 00121 00122 explicit KResolverPrivate(KResolver* _parent, 00123 const QString& _node = QString(), 00124 const QString& _service = QString()) 00125 : parent(_parent), deleteWhenDone(false), waiting(false), 00126 status(0), errorcode(0), syserror(0) 00127 { 00128 input.node = _node; 00129 input.service = _service; 00130 input.flags = 0; 00131 input.familyMask = KResolver::AnyFamily; 00132 input.socktype = 0; 00133 input.protocol = 0; 00134 00135 results.setAddress(_node, _service); 00136 } 00137 }; 00138 00139 namespace Internal 00140 { 00141 struct RequestData 00142 { 00143 // worker threads should not change values in the input data 00144 KNetwork::KResolverPrivate *obj; 00145 const KNetwork::Internal::InputData *input; 00146 KNetwork::KResolverWorkerBase *worker; // worker class 00147 RequestData *requestor; // class that requested us 00148 00149 volatile int nRequests; // how many requests that we made we still have left 00150 }; 00151 00152 /* 00153 * @internal 00154 * This class is the resolver manager 00155 */ 00156 class KResolverManager 00157 { 00158 public: 00159 enum EventTypes 00160 { ResolutionCompleted = 1576 }; // arbitrary value; 00161 00162 /* 00163 * This wait condition is used to notify wait states (KResolver::wait) that 00164 * the resolver manager has finished processing one or more objects. All 00165 * objects in wait state will be woken up and will check if they are done. 00166 * If they aren't, they will go back to sleeping. 00167 */ 00168 QWaitCondition notifyWaiters; 00169 00170 private: 00171 /* 00172 * This variable is used to count the number of threads that are running 00173 */ 00174 volatile unsigned short runningThreads; 00175 00176 /* 00177 * This variable is used to count the number of threads that are currently 00178 * waiting for data. 00179 */ 00180 unsigned short availableThreads; 00181 00182 /* 00183 * This wait condition is used to notify worker threads that there is new 00184 * data available that has to be processed. All worker threads wait on this 00185 * waitcond for a limited amount of time. 00186 */ 00187 QWaitCondition feedWorkers; 00188 00189 // this mutex protects the data in this object 00190 QMutex mutex; 00191 00192 // hold a list of all the current threads we have 00193 QList<KResolverThread*> workers; 00194 00195 // hold a list of all the new requests we have 00196 QList<RequestData*> newRequests; 00197 00198 // hold a list of all the requests in progress we have 00199 QList<RequestData*> currentRequests; 00200 00201 // hold a list of all the workers we have 00202 QList<KNetwork::KResolverWorkerFactoryBase*> workerFactories; 00203 00204 // private constructor 00205 KResolverManager(); 00206 00207 public: 00208 static KResolverManager* manager() KDE_NO_EXPORT; // creates and returns the global manager 00209 00210 // destructor 00211 ~KResolverManager(); 00212 00213 /* 00214 * Register this thread in the pool 00215 */ 00216 void registerThread(KResolverThread* id); 00217 00218 /* 00219 * Unregister this thread from the pool 00220 */ 00221 void unregisterThread(KResolverThread* id); 00222 00223 /* 00224 * Requests new data to work on. 00225 * 00226 * This function should only be called from a worker thread. This function 00227 * is thread-safe. 00228 * 00229 * If there is data to be worked on, this function will return it. If there is 00230 * none, this function will return a null pointer. 00231 */ 00232 RequestData* requestData(KResolverThread* id, int maxWaitTime); 00233 00234 /* 00235 * Releases the resources and returns the resolved data. 00236 * 00237 * This function should only be called from a worker thread. It is 00238 * thread-safe. It does not post the event to the manager. 00239 */ 00240 void releaseData(KResolverThread *id, RequestData* data); 00241 00242 /* 00243 * Registers a new worker class by way of its factory. 00244 * 00245 * This function is NOT thread-safe. 00246 */ 00247 void registerNewWorker(KNetwork::KResolverWorkerFactoryBase *factory); 00248 00249 /* 00250 * Enqueues new resolutions. 00251 */ 00252 void enqueue(KNetwork::KResolver *obj, RequestData* requestor); 00253 00254 /* 00255 * Dispatch a new request 00256 */ 00257 void dispatch(RequestData* data); 00258 00259 /* 00260 * Dequeues a resolution. 00261 */ 00262 void dequeue(KNetwork::KResolver *obj); 00263 00264 /* 00265 * Notifies the manager that the given resolution is about to 00266 * be deleted. This function should only be called by the 00267 * KResolver destructor. 00268 */ 00269 void aboutToBeDeleted(KNetwork::KResolver *obj); 00270 00271 /* 00272 * Notifies the manager that new events are ready. 00273 */ 00274 void newEvent(); 00275 00276 /* 00277 * This function is called by the manager to receive a new event. It operates 00278 * on the eventSemaphore() semaphore, which means it will block till there 00279 * is at least one event to go. 00280 */ 00281 void receiveEvent(); 00282 00283 private: 00284 /* 00285 * finds a suitable worker for this request 00286 */ 00287 KNetwork::KResolverWorkerBase *findWorker(KNetwork::KResolverPrivate *p); 00288 00289 /* 00290 * finds data for this request 00291 */ 00292 RequestData* findData(KResolverThread*); 00293 00294 /* 00295 * Handle completed requests. 00296 * 00297 * This function is called by releaseData above 00298 */ 00299 void handleFinished(); 00300 00301 /* 00302 * Handle one completed request. 00303 * 00304 * This function is called by handleFinished above. 00305 */ 00306 bool handleFinishedItem(RequestData* item); 00307 00308 /* 00309 * Notifies the parent class that this request is done. 00310 * 00311 * This function deletes the request 00312 */ 00313 void doNotifying(RequestData *p); 00314 00315 /* 00316 * Dequeues and notifies an object that is in Queued state 00317 * Returns true if the object is no longer queued; false if it could not 00318 * be dequeued (i.e., it's running) 00319 */ 00320 bool dequeueNew(KNetwork::KResolver* obj); 00321 }; 00322 00323 /* 00324 * @internal 00325 * This class is a worker thread in the resolver system. 00326 * This class must be thread-safe. 00327 */ 00328 class KResolverThread: public QThread 00329 { 00330 private: 00331 // private constructor. Only the manager can create worker threads 00332 KResolverThread(); 00333 RequestData* data; 00334 00335 protected: 00336 virtual void run(); // here the thread starts 00337 00338 friend class KNetwork::Internal::KResolverManager; 00339 friend class KNetwork::KResolverWorkerBase; 00340 00341 public: 00342 bool checkResolver(); // see KResolverWorkerBase::checkResolver 00343 void acquireResolver(); // see KResolverWorkerBase::acquireResolver 00344 void releaseResolver(); // see KResolverWorkerBase::releaseResolver 00345 }; 00346 00347 } // namespace Internal 00348 00349 } // namespace KNetwork 00350 00351 00352 #endif
KDE 4.6 API Reference