kernel/qsocketnotifier.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtCore module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qsocketnotifier.h" -
43 -
44#include "qplatformdefs.h" -
45 -
46#include "qabstracteventdispatcher.h" -
47#include "qcoreapplication.h" -
48 -
49#include "qobject_p.h" -
50#include <private/qthread_p.h> -
51 -
52QT_BEGIN_NAMESPACE -
53 -
54class QSocketNotifierPrivate : public QObjectPrivate -
55{ -
56 Q_DECLARE_PUBLIC(QSocketNotifier) -
57public: -
58 qintptr sockfd; -
59 QSocketNotifier::Type sntype; -
60 bool snenabled; -
61}; -
62 -
63/*! -
64 \class QSocketNotifier -
65 \inmodule QtCore -
66 \brief The QSocketNotifier class provides support for monitoring -
67 activity on a file descriptor. -
68 -
69 \ingroup network -
70 \ingroup io -
71 -
72 The QSocketNotifier makes it possible to integrate Qt's event -
73 loop with other event loops based on file descriptors. File -
74 descriptor action is detected in Qt's main event -
75 loop (QCoreApplication::exec()). -
76 -
77 \target write notifiers -
78 -
79 Once you have opened a device using a low-level (usually -
80 platform-specific) API, you can create a socket notifier to -
81 monitor the file descriptor. The socket notifier is enabled by -
82 default, i.e. it emits the activated() signal whenever a socket -
83 event corresponding to its type occurs. Connect the activated() -
84 signal to the slot you want to be called when an event -
85 corresponding to your socket notifier's type occurs. -
86 -
87 There are three types of socket notifiers: read, write, and -
88 exception. The type is described by the \l Type enum, and must be -
89 specified when constructing the socket notifier. After -
90 construction it can be determined using the type() function. Note -
91 that if you need to monitor both reads and writes for the same -
92 file descriptor, you must create two socket notifiers. Note also -
93 that it is not possible to install two socket notifiers of the -
94 same type (\l Read, \l Write, \l Exception) on the same socket. -
95 -
96 The setEnabled() function allows you to disable as well as enable -
97 the socket notifier. It is generally advisable to explicitly -
98 enable or disable the socket notifier, especially for write -
99 notifiers. A disabled notifier ignores socket events (the same -
100 effect as not creating the socket notifier). Use the isEnabled() -
101 function to determine the notifier's current status. -
102 -
103 Finally, you can use the socket() function to retrieve the -
104 socket identifier. Although the class is called QSocketNotifier, -
105 it is normally used for other types of devices than sockets. -
106 QTcpSocket and QUdpSocket provide notification through signals, so -
107 there is normally no need to use a QSocketNotifier on them. -
108 -
109 \section1 Notes for Windows Users -
110 -
111 The socket passed to QSocketNotifier will become non-blocking, even if -
112 it was created as a blocking socket. -
113 The activated() signal is sometimes triggered by high general activity -
114 on the host, even if there is nothing to read. A subsequent read from -
115 the socket can then fail, the error indicating that there is no data -
116 available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system -
117 limitation, and not a bug in QSocketNotifier. -
118 -
119 To ensure that the socket notifier handles read notifications correctly, -
120 follow these steps when you receive a notification: -
121 -
122 \list 1 -
123 \li Disable the notifier. -
124 \li Read data from the socket. -
125 \li Re-enable the notifier if you are interested in more data (such as after -
126 having written a new command to a remote server). -
127 \endlist -
128 -
129 To ensure that the socket notifier handles write notifications correctly, -
130 follow these steps when you receive a notification: -
131 -
132 \list 1 -
133 \li Disable the notifier. -
134 \li Write as much data as you can (before \c EWOULDBLOCK is returned). -
135 \li Re-enable notifier if you have more data to write. -
136 \endlist -
137 -
138 \b{Further information:} -
139 On Windows, Qt always disables the notifier after getting a notification, -
140 and only re-enables it if more data is expected. For example, if data is -
141 read from the socket and it can be used to read more, or if reading or -
142 writing is not possible because the socket would block, in which case -
143 it is necessary to wait before attempting to read or write again. -
144 -
145 \sa QFile, QProcess, QTcpSocket, QUdpSocket -
146*/ -
147 -
148/*! -
149 \enum QSocketNotifier::Type -
150 -
151 This enum describes the various types of events that a socket -
152 notifier can recognize. The type must be specified when -
153 constructing the socket notifier. -
154 -
155 Note that if you need to monitor both reads and writes for the -
156 same file descriptor, you must create two socket notifiers. Note -
157 also that it is not possible to install two socket notifiers of -
158 the same type (Read, Write, Exception) on the same socket. -
159 -
160 \value Read There is data to be read. -
161 \value Write Data can be written. -
162 \value Exception An exception has occurred. We recommend against using this. -
163 -
164 \sa QSocketNotifier(), type() -
165*/ -
166 -
167/*! -
168 Constructs a socket notifier with the given \a parent. It enables -
169 the \a socket, and watches for events of the given \a type. -
170 -
171 It is generally advisable to explicitly enable or disable the -
172 socket notifier, especially for write notifiers. -
173 -
174 \b{Note for Windows users:} The socket passed to QSocketNotifier -
175 will become non-blocking, even if it was created as a blocking socket. -
176 -
177 \sa setEnabled(), isEnabled() -
178*/ -
179 -
180QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent) -
181 : QObject(*new QSocketNotifierPrivate, parent) -
182{ -
183 Q_D(QSocketNotifier);
executed (the execution status of this line is deduced): QSocketNotifierPrivate * const d = d_func();
-
184 if (socket < 0)
partially evaluated: socket < 0
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:17761
0-17761
185 qWarning("QSocketNotifier: Invalid socket specified");
never executed: QMessageLogger("kernel/qsocketnotifier.cpp", 185, __PRETTY_FUNCTION__).warning("QSocketNotifier: Invalid socket specified");
0
186 d->sockfd = socket;
executed (the execution status of this line is deduced): d->sockfd = socket;
-
187 d->sntype = type;
executed (the execution status of this line is deduced): d->sntype = type;
-
188 d->snenabled = true;
executed (the execution status of this line is deduced): d->snenabled = true;
-
189 -
190 if (!d->threadData->eventDispatcher) {
partially evaluated: !d->threadData->eventDispatcher
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:17761
0-17761
191 qWarning("QSocketNotifier: Can only be used with threads started with QThread");
never executed (the execution status of this line is deduced): QMessageLogger("kernel/qsocketnotifier.cpp", 191, __PRETTY_FUNCTION__).warning("QSocketNotifier: Can only be used with threads started with QThread");
-
192 } else {
never executed: }
0
193 d->threadData->eventDispatcher->registerSocketNotifier(this);
executed (the execution status of this line is deduced): d->threadData->eventDispatcher->registerSocketNotifier(this);
-
194 }
executed: }
Execution Count:17760
17760
195} -
196 -
197/*! -
198 Destroys this socket notifier. -
199*/ -
200 -
201QSocketNotifier::~QSocketNotifier() -
202{ -
203 setEnabled(false);
executed (the execution status of this line is deduced): setEnabled(false);
-
204}
executed: }
Execution Count:18312
18312
205 -
206 -
207/*! -
208 \fn void QSocketNotifier::activated(int socket) -
209 -
210 This signal is emitted whenever the socket notifier is enabled and -
211 a socket event corresponding to its \l {Type}{type} occurs. -
212 -
213 The socket identifier is passed in the \a socket parameter. -
214 -
215 \sa type(), socket() -
216*/ -
217 -
218 -
219/*! -
220 Returns the socket identifier specified to the constructor. -
221 -
222 \sa type() -
223*/ -
224qintptr QSocketNotifier::socket() const -
225{ -
226 Q_D(const QSocketNotifier);
executed (the execution status of this line is deduced): const QSocketNotifierPrivate * const d = d_func();
-
227 return d->sockfd;
executed: return d->sockfd;
Execution Count:43694
43694
228} -
229 -
230/*! -
231 Returns the socket event type specified to the constructor. -
232 -
233 \sa socket() -
234*/ -
235QSocketNotifier::Type QSocketNotifier::type() const -
236{ -
237 Q_D(const QSocketNotifier);
executed (the execution status of this line is deduced): const QSocketNotifierPrivate * const d = d_func();
-
238 return d->sntype;
executed: return d->sntype;
Execution Count:43696
43696
239} -
240 -
241/*! -
242 Returns true if the notifier is enabled; otherwise returns false. -
243 -
244 \sa setEnabled() -
245*/ -
246bool QSocketNotifier::isEnabled() const -
247{ -
248 Q_D(const QSocketNotifier);
executed (the execution status of this line is deduced): const QSocketNotifierPrivate * const d = d_func();
-
249 return d->snenabled;
executed: return d->snenabled;
Execution Count:461140
461140
250} -
251 -
252/*! -
253 If \a enable is true, the notifier is enabled; otherwise the notifier -
254 is disabled. -
255 -
256 The notifier is enabled by default, i.e. it emits the activated() -
257 signal whenever a socket event corresponding to its -
258 \l{type()}{type} occurs. If it is disabled, it ignores socket -
259 events (the same effect as not creating the socket notifier). -
260 -
261 Write notifiers should normally be disabled immediately after the -
262 activated() signal has been emitted -
263 -
264 \sa isEnabled(), activated() -
265*/ -
266 -
267void QSocketNotifier::setEnabled(bool enable) -
268{ -
269 Q_D(QSocketNotifier);
executed (the execution status of this line is deduced): QSocketNotifierPrivate * const d = d_func();
-
270 if (d->sockfd < 0)
partially evaluated: d->sockfd < 0
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1111499
0-1111499
271 return;
never executed: return;
0
272 if (d->snenabled == enable) // no change
evaluated: d->snenabled == enable
TRUEFALSE
yes
Evaluation Count:1041502
yes
Evaluation Count:69999
69999-1041502
273 return;
executed: return;
Execution Count:1041502
1041502
274 d->snenabled = enable;
executed (the execution status of this line is deduced): d->snenabled = enable;
-
275 -
276 if (!d->threadData->eventDispatcher) // perhaps application/thread is shutting down
evaluated: !d->threadData->eventDispatcher
TRUEFALSE
yes
Evaluation Count:503
yes
Evaluation Count:69502
503-69502
277 return;
executed: return;
Execution Count:503
503
278 if (d->snenabled)
evaluated: d->snenabled
TRUEFALSE
yes
Evaluation Count:25940
yes
Evaluation Count:43565
25940-43565
279 d->threadData->eventDispatcher->registerSocketNotifier(this);
executed: d->threadData->eventDispatcher->registerSocketNotifier(this);
Execution Count:25939
25939
280 else -
281 d->threadData->eventDispatcher->unregisterSocketNotifier(this);
executed: d->threadData->eventDispatcher->unregisterSocketNotifier(this);
Execution Count:43564
43564
282} -
283 -
284 -
285/*!\reimp -
286*/ -
287bool QSocketNotifier::event(QEvent *e) -
288{ -
289 Q_D(QSocketNotifier);
executed (the execution status of this line is deduced): QSocketNotifierPrivate * const d = d_func();
-
290 // Emits the activated() signal when a QEvent::SockAct or QEvent::SockClose is -
291 // received. -
292 if (e->type() == QEvent::ThreadChange) {
evaluated: e->type() == QEvent::ThreadChange
TRUEFALSE
yes
Evaluation Count:9
yes
Evaluation Count:2290
9-2290
293 if (d->snenabled) {
evaluated: d->snenabled
TRUEFALSE
yes
Evaluation Count:7
yes
Evaluation Count:2
2-7
294 QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
executed (the execution status of this line is deduced): QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
-
295 Q_ARG(bool, d->snenabled));
executed (the execution status of this line is deduced): QArgument<bool >("bool", d->snenabled));
-
296 setEnabled(false);
executed (the execution status of this line is deduced): setEnabled(false);
-
297 }
executed: }
Execution Count:7
7
298 }
executed: }
Execution Count:9
9
299 QObject::event(e); // will activate filters
executed (the execution status of this line is deduced): QObject::event(e);
-
300 if ((e->type() == QEvent::SockAct) || (e->type() == QEvent::SockClose)) {
evaluated: (e->type() == QEvent::SockAct)
TRUEFALSE
yes
Evaluation Count:2039
yes
Evaluation Count:261
partially evaluated: (e->type() == QEvent::SockClose)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:261
0-2039
301 emit activated(d->sockfd, QPrivateSignal());
executed (the execution status of this line is deduced): activated(d->sockfd, QPrivateSignal());
-
302 return true;
executed: return true;
Execution Count:2038
2038
303 } -
304 return false;
executed: return false;
Execution Count:261
261
305} -
306 -
307QT_END_NAMESPACE -
308 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial