PageRenderTime 23ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/kdecore/network/k3resolver_p.h

https://github.com/vasi/kdelibs
C Header | 352 lines | 151 code | 59 blank | 142 comment | 4 complexity | d8e3ce54c663a04f4a6c4236177bd4cc MD5 | raw file
  1. /* -*- C++ -*-
  2. * Copyright (C) 2003-2005 Thiago Macieira <thiago@kde.org>
  3. *
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining
  6. * a copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included
  14. * in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. #ifndef KRESOLVER_P_H
  25. #define KRESOLVER_P_H
  26. #include <config.h>
  27. #include <config-network.h>
  28. #include <sys/types.h>
  29. #include <QByteArray>
  30. #include <QList>
  31. #include <QThread>
  32. #include <QMutex>
  33. #include <QWaitCondition>
  34. #include <QSemaphore>
  35. #include <QEvent>
  36. #include "k3resolver.h"
  37. /* decide whether we need a mutex */
  38. #if !defined(HAVE_GETPROTOBYNAME_R) || !defined(HAVE_GETSERVBYNAME_R) || !defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETSERVBYPORT_R)
  39. # define NEED_MUTEX
  40. extern QMutex getXXbyYYmutex;
  41. #endif
  42. /* some systems have the functions, but don't declare them */
  43. #if defined(HAVE_GETSERVBYNAME_R) && !HAVE_GETSERVBYNAME_R_PROTO
  44. extern "C" {
  45. struct servent;
  46. extern int getservbyname_r(const char* serv, const char* proto,
  47. struct servent* servbuf,
  48. char* buf, size_t buflen,
  49. struct servent** result);
  50. extern int getservbyport_r(int port, const char* proto,
  51. struct servent* servbuf,
  52. char* buf, size_t buflen,
  53. struct servent** result);
  54. struct protoent;
  55. extern int getprotobyname_r(const char* proto, struct protoent* protobuf,
  56. char *buf, size_t buflen,
  57. struct protoent** result);
  58. extern int getprotobynumber_r(int proto, struct protoent* protobuf,
  59. char *buf, size_t buflen,
  60. struct protoent** result);
  61. }
  62. #endif
  63. /* decide whether res_init is thread-safe or not */
  64. #if defined(__GLIBC__)
  65. # undef RES_INIT_THREADSAFE
  66. #endif
  67. namespace KNetwork
  68. {
  69. // defined in network/qresolverworkerbase.h
  70. class KResolverWorkerBase;
  71. class KResolverWorkerFactoryBase;
  72. class KResolverPrivate;
  73. namespace Internal
  74. {
  75. class KResolverManager;
  76. class KResolverThread;
  77. struct RequestData;
  78. struct InputData
  79. {
  80. QString node, service;
  81. QByteArray protocolName;
  82. int flags;
  83. int familyMask;
  84. int socktype;
  85. int protocol;
  86. };
  87. }
  88. class KResolverPrivate
  89. {
  90. public:
  91. // parent class. Should never be changed!
  92. KResolver* parent;
  93. bool deleteWhenDone : 1;
  94. bool waiting : 1;
  95. // class status. Should not be changed by worker threads!
  96. volatile int status;
  97. volatile int errorcode, syserror;
  98. // input data. Should not be changed by worker threads!
  99. Internal::InputData input;
  100. // mutex
  101. QMutex mutex;
  102. // output data
  103. KResolverResults results;
  104. explicit KResolverPrivate(KResolver* _parent,
  105. const QString& _node = QString(),
  106. const QString& _service = QString())
  107. : parent(_parent), deleteWhenDone(false), waiting(false),
  108. status(0), errorcode(0), syserror(0)
  109. {
  110. input.node = _node;
  111. input.service = _service;
  112. input.flags = 0;
  113. input.familyMask = KResolver::AnyFamily;
  114. input.socktype = 0;
  115. input.protocol = 0;
  116. results.setAddress(_node, _service);
  117. }
  118. };
  119. namespace Internal
  120. {
  121. struct RequestData
  122. {
  123. // worker threads should not change values in the input data
  124. KNetwork::KResolverPrivate *obj;
  125. const KNetwork::Internal::InputData *input;
  126. KNetwork::KResolverWorkerBase *worker; // worker class
  127. RequestData *requestor; // class that requested us
  128. volatile int nRequests; // how many requests that we made we still have left
  129. };
  130. /*
  131. * @internal
  132. * This class is the resolver manager
  133. */
  134. class KResolverManager
  135. {
  136. public:
  137. enum EventTypes
  138. { ResolutionCompleted = 1576 }; // arbitrary value;
  139. /*
  140. * This wait condition is used to notify wait states (KResolver::wait) that
  141. * the resolver manager has finished processing one or more objects. All
  142. * objects in wait state will be woken up and will check if they are done.
  143. * If they aren't, they will go back to sleeping.
  144. */
  145. QWaitCondition notifyWaiters;
  146. private:
  147. /*
  148. * This variable is used to count the number of threads that are running
  149. */
  150. volatile unsigned short runningThreads;
  151. /*
  152. * This variable is used to count the number of threads that are currently
  153. * waiting for data.
  154. */
  155. unsigned short availableThreads;
  156. /*
  157. * This wait condition is used to notify worker threads that there is new
  158. * data available that has to be processed. All worker threads wait on this
  159. * waitcond for a limited amount of time.
  160. */
  161. QWaitCondition feedWorkers;
  162. // this mutex protects the data in this object
  163. QMutex mutex;
  164. // hold a list of all the current threads we have
  165. QList<KResolverThread*> workers;
  166. // hold a list of all the new requests we have
  167. QList<RequestData*> newRequests;
  168. // hold a list of all the requests in progress we have
  169. QList<RequestData*> currentRequests;
  170. // hold a list of all the workers we have
  171. QList<KNetwork::KResolverWorkerFactoryBase*> workerFactories;
  172. // private constructor
  173. KResolverManager();
  174. public:
  175. static KResolverManager* manager() KDE_NO_EXPORT; // creates and returns the global manager
  176. // destructor
  177. ~KResolverManager();
  178. /*
  179. * Register this thread in the pool
  180. */
  181. void registerThread(KResolverThread* id);
  182. /*
  183. * Unregister this thread from the pool
  184. */
  185. void unregisterThread(KResolverThread* id);
  186. /*
  187. * Requests new data to work on.
  188. *
  189. * This function should only be called from a worker thread. This function
  190. * is thread-safe.
  191. *
  192. * If there is data to be worked on, this function will return it. If there is
  193. * none, this function will return a null pointer.
  194. */
  195. RequestData* requestData(KResolverThread* id, int maxWaitTime);
  196. /*
  197. * Releases the resources and returns the resolved data.
  198. *
  199. * This function should only be called from a worker thread. It is
  200. * thread-safe. It does not post the event to the manager.
  201. */
  202. void releaseData(KResolverThread *id, RequestData* data);
  203. /*
  204. * Registers a new worker class by way of its factory.
  205. *
  206. * This function is NOT thread-safe.
  207. */
  208. void registerNewWorker(KNetwork::KResolverWorkerFactoryBase *factory);
  209. /*
  210. * Enqueues new resolutions.
  211. */
  212. void enqueue(KNetwork::KResolver *obj, RequestData* requestor);
  213. /*
  214. * Dispatch a new request
  215. */
  216. void dispatch(RequestData* data);
  217. /*
  218. * Dequeues a resolution.
  219. */
  220. void dequeue(KNetwork::KResolver *obj);
  221. /*
  222. * Notifies the manager that the given resolution is about to
  223. * be deleted. This function should only be called by the
  224. * KResolver destructor.
  225. */
  226. void aboutToBeDeleted(KNetwork::KResolver *obj);
  227. /*
  228. * Notifies the manager that new events are ready.
  229. */
  230. void newEvent();
  231. /*
  232. * This function is called by the manager to receive a new event. It operates
  233. * on the eventSemaphore() semaphore, which means it will block till there
  234. * is at least one event to go.
  235. */
  236. void receiveEvent();
  237. private:
  238. /*
  239. * finds a suitable worker for this request
  240. */
  241. KNetwork::KResolverWorkerBase *findWorker(KNetwork::KResolverPrivate *p);
  242. /*
  243. * finds data for this request
  244. */
  245. RequestData* findData(KResolverThread*);
  246. /*
  247. * Handle completed requests.
  248. *
  249. * This function is called by releaseData above
  250. */
  251. void handleFinished();
  252. /*
  253. * Handle one completed request.
  254. *
  255. * This function is called by handleFinished above.
  256. */
  257. bool handleFinishedItem(RequestData* item);
  258. /*
  259. * Notifies the parent class that this request is done.
  260. *
  261. * This function deletes the request
  262. */
  263. void doNotifying(RequestData *p);
  264. /*
  265. * Dequeues and notifies an object that is in Queued state
  266. * Returns true if the object is no longer queued; false if it could not
  267. * be dequeued (i.e., it's running)
  268. */
  269. bool dequeueNew(KNetwork::KResolver* obj);
  270. };
  271. /*
  272. * @internal
  273. * This class is a worker thread in the resolver system.
  274. * This class must be thread-safe.
  275. */
  276. class KResolverThread: public QThread
  277. {
  278. private:
  279. // private constructor. Only the manager can create worker threads
  280. KResolverThread();
  281. RequestData* data;
  282. protected:
  283. virtual void run(); // here the thread starts
  284. friend class KNetwork::Internal::KResolverManager;
  285. friend class KNetwork::KResolverWorkerBase;
  286. public:
  287. bool checkResolver(); // see KResolverWorkerBase::checkResolver
  288. void acquireResolver(); // see KResolverWorkerBase::acquireResolver
  289. void releaseResolver(); // see KResolverWorkerBase::releaseResolver
  290. };
  291. } // namespace Internal
  292. } // namespace KNetwork
  293. #endif