| Line | Source Code | Coverage |
|---|
| 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 | | - |
| 52 | QT_BEGIN_NAMESPACE | - |
| 53 | | - |
| 54 | class QSocketNotifierPrivate : public QObjectPrivate | - |
| 55 | { | - |
| 56 | Q_DECLARE_PUBLIC(QSocketNotifier) | - |
| 57 | public: | - |
| 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 | | - |
| 180 | QSocketNotifier::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| 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| 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 { | 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 | | - |
| 201 | QSocketNotifier::~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 | */ | - |
| 224 | qintptr 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 | */ | - |
| 235 | QSocketNotifier::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 | */ | - |
| 246 | bool 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 | | - |
| 267 | void 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| no Evaluation Count:0 | yes Evaluation Count:1111499 |
| 0-1111499 |
| 271 | return; | 0 |
| 272 | if (d->snenabled == enable) // no change evaluated: d->snenabled == enable| 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| 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| 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 | */ | - |
| 287 | bool 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| yes Evaluation Count:9 | yes Evaluation Count:2290 |
| 9-2290 |
| 293 | if (d->snenabled) { evaluated: d->snenabled| 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)| yes Evaluation Count:2039 | yes Evaluation Count:261 |
partially evaluated: (e->type() == QEvent::SockClose)| 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 | | - |
| 307 | QT_END_NAMESPACE | - |
| 308 | | - |
| | |