KD SOAP API Documentation  2.1
KDSoapThreadPool.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Soap project.
4 **
5 ** SPDX-FileCopyrightText: 2010-2022 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
10 #include "KDSoapThreadPool.h"
11 #include "KDSoapServerThread_p.h"
12 #include <QDebug>
13 
14 class KDSoapThreadPool::Private
15 {
16 public:
17  Private()
18  : m_maxThreadCount(QThread::idealThreadCount())
19  {
20  }
21 
22  KDSoapServerThread *chooseNextThread();
23 
24  int m_maxThreadCount;
25  typedef QList<KDSoapServerThread *> ThreadCollection;
26  ThreadCollection m_threads;
27 };
28 
30  : QObject(parent)
31  , d(new Private)
32 {
33 }
34 
36 {
37  // ask all threads to finish, then delete them all
38  for (KDSoapServerThread *thread : qAsConst(d->m_threads)) {
39  thread->quitThread();
40  }
41  for (KDSoapServerThread *thread : qAsConst(d->m_threads)) {
42  thread->wait();
43  delete thread;
44  }
45 
46  delete d;
47 }
48 
49 void KDSoapThreadPool::setMaxThreadCount(int maxThreadCount)
50 {
51  d->m_maxThreadCount = maxThreadCount;
52 }
53 
55 {
56  return d->m_maxThreadCount;
57 }
58 
59 KDSoapServerThread *KDSoapThreadPool::Private::chooseNextThread()
60 {
61  KDSoapServerThread *chosenThread = nullptr;
62  // Try to pick an existing thread
63  int minSocketCount = 0;
64  KDSoapServerThread *bestThread = nullptr;
65  for (KDSoapServerThread *thr : qAsConst(m_threads)) {
66  // We look at the amount of sockets connected to each thread, and pick the less busy one.
67  // Note that this isn't fully accurate, due to Keep-Alive: it's possible for long-term
68  // idling clients to be all on one thread, and active clients on another one, and this
69  // wouldn't use CPU fully. But this is probably still better than no keep-alive (much more
70  // connection overhead). Maybe we have to look at sockets who made a request in the last
71  // N seconds... but the past is no indication of the future.
72  const int sc = thr->socketCount();
73  if (sc == 0) { // Perfect, an idling thread
74  // qDebug() << "Picked" << thr << "since it was idling";
75  chosenThread = thr;
76  break;
77  }
78  if (!bestThread || sc < minSocketCount) {
79  minSocketCount = sc;
80  bestThread = thr;
81  }
82  }
83 
84  // Use an existing non-idling thread, if we reached maxThreads
85  if (!chosenThread && bestThread && m_threads.count() == m_maxThreadCount) {
86  chosenThread = bestThread;
87  }
88 
89  // Create new thread
90  if (!chosenThread) {
91  chosenThread = new KDSoapServerThread(nullptr);
92  // qDebug() << "Creating KDSoapServerThread" << chosenThread;
93  m_threads.append(chosenThread);
94  chosenThread->startThread();
95  }
96  return chosenThread;
97 }
98 
99 void KDSoapThreadPool::handleIncomingConnection(int socketDescriptor, KDSoapServer *server)
100 {
101  // First, pick or create a thread.
102  KDSoapServerThread *chosenThread = d->chooseNextThread();
103 
104  // Then create the socket, and register it in the corresponding socket-pool, and move it to the thread.
105  chosenThread->handleIncomingConnection(socketDescriptor, server);
106 }
107 
109 {
110  int sc = 0;
111  for (KDSoapServerThread *thread : qAsConst(d->m_threads)) {
112  sc += thread->socketCountForServer(server);
113  }
114  return sc;
115 }
116 
118 {
119  QSemaphore readyThreads;
120  for (KDSoapServerThread *thread : qAsConst(d->m_threads)) {
121  thread->disconnectSocketsForServer(server, readyThreads);
122  }
123  // Wait for all threads to have disconnected their sockets
124  readyThreads.acquire(d->m_threads.count());
125 }
126 
128 {
129  int sc = 0;
130  for (KDSoapServerThread *thread : qAsConst(d->m_threads)) {
131  sc += thread->totalConnectionCountForServer(server);
132  }
133  return sc;
134 }
135 
137 {
138  for (KDSoapServerThread *thread : qAsConst(d->m_threads)) {
139  thread->resetTotalConnectionCountForServer(server);
140  }
141 }
142 
143 #include "moc_KDSoapThreadPool.cpp"
void handleIncomingConnection(int socketDescriptor, KDSoapServer *server)
int maxThreadCount() const
int totalConnectionCount(const KDSoapServer *server) const
void resetTotalConnectionCount(const KDSoapServer *server)
void setMaxThreadCount(int maxThreadCount)
KDSoapThreadPool(QObject *parent=0)
int numConnectedSockets(const KDSoapServer *server) const
void disconnectSockets(KDSoapServer *server)

© 2010-2022 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-soap/
Generated on Tue Jun 13 2023 12:18:34 for KD SOAP API Documentation by doxygen 1.9.1