kdecore Library API Documentation

kresolver_p.h

00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003-2005 Thiago Macieira <thiago.macieira@kdemail.net>
00003  *
00004  *  Permission is hereby granted, free of charge, to any person obtaining
00005  *  a copy of this software and associated documentation files (the
00006  *  "Software"), to deal in the Software without restriction, including
00007  *  without limitation the rights to use, copy, modify, merge, publish,
00008  *  distribute, sublicense, and/or sell copies of the Software, and to
00009  *  permit persons to whom the Software is furnished to do so, subject to
00010  *  the following conditions:
00011  *
00012  *  The above copyright notice and this permission notice shall be included 
00013  *  in all copies or substantial portions of the Software.
00014  *
00015  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00016  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00018  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00019  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00020  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00021  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022  */
00023 
00024 #ifndef KRESOLVER_P_H
00025 #define KRESOLVER_P_H
00026 
00027 #include <config.h>
00028 
00029 #include <qstring.h>
00030 #include <qcstring.h>
00031 #include <qvaluelist.h>
00032 #include <qptrlist.h>
00033 #include <qptrqueue.h>
00034 #include <qthread.h>
00035 #include <qmutex.h>
00036 #include <qwaitcondition.h>
00037 #include <qsemaphore.h>
00038 #include <qevent.h>
00039 
00040 #include "kdemacros.h"
00041 #include "kresolver.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_DECL_GETSERVBYNAME_R
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's context is shared by all threads, 
00073    or is per-thread */
00074 #define SHARED_LIBRESOLV
00075 #if defined(__GLIBC__)
00076 # undef SHARED_LIBRESOLV
00077 #endif
00078 
00079 namespace KNetwork
00080 {
00081 
00082   // defined in network/qresolverworkerbase.h
00083   class KResolverWorkerBase;
00084   class KResolverWorkerFactoryBase;
00085 
00086   class KResolverPrivate
00087   {
00088   public:
00089     // parent class. Should never be changed!
00090     KResolver* parent;
00091     bool deleteWhenDone : 1;
00092     bool waiting : 1;
00093 
00094     // class status. Should not be changed by worker threads!
00095     volatile int status;
00096     volatile int errorcode, syserror;
00097 
00098     // input data. Should not be changed by worker threads!
00099     struct InputData
00100     {
00101       QString node, service;
00102       QCString protocolName;
00103       int flags;
00104       int familyMask;
00105       int socktype;
00106       int protocol;
00107     } input;
00108 
00109     // mutex
00110     QMutex mutex;
00111 
00112     // output data
00113     KResolverResults results;
00114 
00115     KResolverPrivate(KResolver* _parent,
00116              const QString& _node = QString::null, 
00117              const QString& _service = QString::null)
00118       : parent(_parent), deleteWhenDone(false), waiting(false),
00119     status(0), errorcode(0), syserror(0)
00120     {
00121       input.node = _node;
00122       input.service = _service;
00123       input.flags = 0;
00124       input.familyMask = KResolver::AnyFamily;
00125       input.socktype = 0;
00126       input.protocol = 0;
00127 
00128       results.setAddress(_node, _service);
00129     }
00130   };
00131 
00132   namespace Internal
00133   {
00134     class KResolverManager;
00135     class KResolverThread;
00136 
00137     struct RequestData
00138     {
00139       // worker threads should not change values in the input data
00140       KNetwork::KResolverPrivate *obj;
00141       const KNetwork::KResolverPrivate::InputData *input;
00142       KNetwork::KResolverWorkerBase *worker; // worker class
00143       RequestData *requestor; // class that requested us
00144 
00145       volatile int nRequests; // how many requests that we made we still have left
00146     };
00147 
00148     /*
00149      * @internal
00150      * This class is the resolver manager
00151      */
00152     class KResolverManager
00153     {
00154     public:
00155       enum EventTypes
00156     { ResolutionCompleted = 1576 }; // arbitrary value;
00157 
00158       /*
00159        * This wait condition is used to notify wait states (KResolver::wait) that
00160        * the resolver manager has finished processing one or more objects. All
00161        * objects in wait state will be woken up and will check if they are done.
00162        * If they aren't, they will go back to sleeping.
00163        */
00164       QWaitCondition notifyWaiters;
00165 
00166     private:
00167       /*
00168        * This variable is used to count the number of threads that are running
00169        */
00170       volatile unsigned short runningThreads;
00171 
00172       /*
00173        * This variable is used to count the number of threads that are currently
00174        * waiting for data.
00175        */
00176       unsigned short availableThreads;
00177 
00178       /*
00179        * This wait condition is used to notify worker threads that there is new
00180        * data available that has to be processed. All worker threads wait on this
00181        * waitcond for a limited amount of time.
00182        */
00183       QWaitCondition feedWorkers;
00184 
00185       // this mutex protects the data in this object
00186       QMutex mutex;
00187 
00188       // hold a list of all the current threads we have
00189       QPtrList<KResolverThread> workers;
00190 
00191       // hold a list of all the new requests we have
00192       QPtrList<RequestData> newRequests;
00193 
00194       // hold a list of all the requests in progress we have
00195       QPtrList<RequestData> currentRequests;
00196 
00197       // hold a list of all the workers we have
00198       QPtrList<KNetwork::KResolverWorkerFactoryBase> workerFactories;
00199 
00200       // private constructor
00201       KResolverManager();
00202 
00203     public:
00204       static KResolverManager* manager() KDE_NO_EXPORT; // creates and returns the global manager
00205 
00206       // destructor
00207       ~KResolverManager();
00208 
00209       /*
00210        * Register this thread in the pool
00211        */
00212       void registerThread(KResolverThread* id);
00213 
00214       /*
00215        * Unregister this thread from the pool
00216        */
00217       void unregisterThread(KResolverThread* id);
00218 
00219       /*
00220        * Requests new data to work on.
00221        *
00222        * This function should only be called from a worker thread. This function
00223        * is thread-safe.
00224        *
00225        * If there is data to be worked on, this function will return it. If there is
00226        * none, this function will return a null pointer.
00227        */
00228       RequestData* requestData(KResolverThread* id, int maxWaitTime);
00229 
00230       /*
00231        * Releases the resources and returns the resolved data.
00232        *
00233        * This function should only be called from a worker thread. It is
00234        * thread-safe. It does not post the event to the manager.
00235        */
00236       void releaseData(KResolverThread *id, RequestData* data);
00237 
00238       /*
00239        * Registers a new worker class by way of its factory.
00240        *
00241        * This function is NOT thread-safe.
00242        */
00243       void registerNewWorker(KNetwork::KResolverWorkerFactoryBase *factory);
00244 
00245       /*
00246        * Enqueues new resolutions.
00247        */
00248       void enqueue(KNetwork::KResolver *obj, RequestData* requestor);
00249 
00250       /*
00251        * Dispatch a new request
00252        */
00253       void dispatch(RequestData* data);
00254 
00255       /*
00256        * Dequeues a resolution.
00257        */
00258       void dequeue(KNetwork::KResolver *obj);
00259 
00260       /*
00261        * Notifies the manager that the given resolution is about to
00262        * be deleted. This function should only be called by the
00263        * KResolver destructor.
00264        */
00265       void aboutToBeDeleted(KNetwork::KResolver *obj);
00266 
00267       /*
00268        * Notifies the manager that new events are ready.
00269        */
00270       void newEvent();
00271 
00272       /*
00273        * This function is called by the manager to receive a new event. It operates
00274        * on the @ref eventSemaphore semaphore, which means it will block till there
00275        * is at least one event to go.
00276        */
00277       void receiveEvent();
00278 
00279     private:
00280       /*
00281        * finds a suitable worker for this request
00282        */
00283       KNetwork::KResolverWorkerBase *findWorker(KNetwork::KResolverPrivate *p);
00284 
00285       /*
00286        * finds data for this request
00287        */
00288       RequestData* findData(KResolverThread*);
00289 
00290       /*
00291        * Handle completed requests.
00292        *
00293        * This function is called by releaseData above
00294        */
00295       void handleFinished();
00296 
00297       /*
00298        * Handle one completed request.
00299        *
00300        * This function is called by handleFinished above.
00301        */
00302       bool handleFinishedItem(RequestData* item);
00303 
00304       /*
00305        * Notifies the parent class that this request is done.
00306        *
00307        * This function deletes the request
00308        */
00309       void doNotifying(RequestData *p);
00310 
00311       /*
00312        * Dequeues and notifies an object that is in Queued state
00313        * Returns true if the object is no longer queued; false if it could not 
00314        * be dequeued (i.e., it's running)
00315        */
00316       bool dequeueNew(KNetwork::KResolver* obj);
00317     };
00318 
00319     /*
00320      * @internal
00321      * This class is a worker thread in the resolver system.
00322      * This class must be thread-safe.
00323      */
00324     class KResolverThread: public QThread
00325     {
00326     public:
00327       // private constructor. Only the manager can create worker threads
00328       KResolverThread();
00329       RequestData* data;
00330   
00331     protected:
00332       virtual void run();       // here the thread starts
00333 
00334       friend class KNetwork::Internal::KResolverManager;
00335       friend class KNetwork::KResolverWorkerBase;
00336     };
00337 
00338   } // namespace Internal
00339 
00340 } // namespace KNetwork
00341 
00342 
00343 #endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Jan 15 13:32:30 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003