src/corelib/kernel/qsocketnotifier.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    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 /*!
       
    55     \class QSocketNotifier
       
    56     \brief The QSocketNotifier class provides support for monitoring
       
    57     activity on a file descriptor.
       
    58 
       
    59     \ingroup network
       
    60     \ingroup io
       
    61 
       
    62     The QSocketNotifier makes it possible to integrate Qt's event
       
    63     loop with other event loops based on file descriptors. For
       
    64     example, the \l{CORBA Framework} uses it to process CORBA
       
    65     events.  File descriptor action is detected in Qt's main event
       
    66     loop (QCoreApplication::exec()).
       
    67 
       
    68     \target write notifiers
       
    69 
       
    70     Once you have opened a device using a low-level (usually
       
    71     platform-specific) API, you can create a socket notifier to
       
    72     monitor the file descriptor. The socket notifier is enabled by
       
    73     default, i.e. it emits the activated() signal whenever a socket
       
    74     event corresponding to its type occurs. Connect the activated()
       
    75     signal to the slot you want to be called when an event
       
    76     corresponding to your socket notifier's type occurs.
       
    77 
       
    78     There are three types of socket notifiers: read, write, and
       
    79     exception. The type is described by the \l Type enum, and must be
       
    80     specified when constructing the socket notifier. After
       
    81     construction it can be determined using the type() function. Note
       
    82     that if you need to monitor both reads and writes for the same
       
    83     file descriptor, you must create two socket notifiers. Note also
       
    84     that it is not possible to install two socket notifiers of the
       
    85     same type (\l Read, \l Write, \l Exception) on the same socket.
       
    86 
       
    87     The setEnabled() function allows you to disable as well as enable
       
    88     the socket notifier. It is generally advisable to explicitly
       
    89     enable or disable the socket notifier, especially for write
       
    90     notifiers. A disabled notifier ignores socket events (the same
       
    91     effect as not creating the socket notifier). Use the isEnabled()
       
    92     function to determine the notifier's current status.
       
    93 
       
    94     Finally, you can use the socket() function to retrieve the
       
    95     socket identifier.  Although the class is called QSocketNotifier,
       
    96     it is normally used for other types of devices than sockets.
       
    97     QTcpSocket and QUdpSocket provide notification through signals, so
       
    98     there is normally no need to use a QSocketNotifier on them.
       
    99 
       
   100     \section1 Notes for Windows Users
       
   101 
       
   102     The socket passed to QSocketNotifier will become non-blocking, even if
       
   103     it was created as a blocking socket.
       
   104     The activated() signal is sometimes triggered by high general activity
       
   105     on the host, even if there is nothing to read. A subsequent read from
       
   106     the socket can then fail, the error indicating that there is no data
       
   107     available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system
       
   108     limitation, and not a bug in QSocketNotifier.
       
   109 
       
   110     To ensure that the socket notifier handles read notifications correctly,
       
   111     follow these steps when you receive a notification:
       
   112 
       
   113     \list 1
       
   114     \o Disable the notifier.
       
   115     \o Read data from the socket.
       
   116     \o Re-enable the notifier if you are interested in more data (such as after
       
   117        having written a new command to a remote server).
       
   118     \endlist
       
   119 
       
   120     To ensure that the socket notifier handles write notifications correctly,
       
   121     follow these steps when you receive a notification:
       
   122 
       
   123     \list 1
       
   124     \o Disable the notifier.
       
   125     \o Write as much data as you can (before \c EWOULDBLOCK is returned).
       
   126     \o Re-enable notifier if you have more data to write.
       
   127     \endlist
       
   128 
       
   129     \bold{Further information:}
       
   130     On Windows, Qt always disables the notifier after getting a notification,
       
   131     and only re-enables it if more data is expected. For example, if data is
       
   132     read from the socket and it can be used to read more, or if reading or
       
   133     writing is not possible because the socket would block, in which case
       
   134     it is necessary to wait before attempting to read or write again.
       
   135 
       
   136     \sa QFile, QProcess, QTcpSocket, QUdpSocket
       
   137 */
       
   138 
       
   139 /*!
       
   140     \enum QSocketNotifier::Type
       
   141 
       
   142     This enum describes the various types of events that a socket
       
   143     notifier can recognize. The type must be specified when
       
   144     constructing the socket notifier.
       
   145 
       
   146     Note that if you need to monitor both reads and writes for the
       
   147     same file descriptor, you must create two socket notifiers. Note
       
   148     also that it is not possible to install two socket notifiers of
       
   149     the same type (Read, Write, Exception) on the same socket.
       
   150 
       
   151     \value Read      There is data to be read.
       
   152     \value Write      Data can be written.
       
   153     \value Exception  An exception has occurred. We recommend against using this.
       
   154 
       
   155     \sa QSocketNotifier(), type()
       
   156 */
       
   157 
       
   158 /*!
       
   159     Constructs a socket notifier with the given \a parent. It enables
       
   160     the \a socket, and watches for events of the given \a type.
       
   161 
       
   162     It is generally advisable to explicitly enable or disable the
       
   163     socket notifier, especially for write notifiers.
       
   164 
       
   165     \bold{Note for Windows users:} The socket passed to QSocketNotifier
       
   166     will become non-blocking, even if it was created as a blocking socket.
       
   167 
       
   168     \sa setEnabled(), isEnabled()
       
   169 */
       
   170 
       
   171 QSocketNotifier::QSocketNotifier(int socket, Type type, QObject *parent)
       
   172     : QObject(parent)
       
   173 {
       
   174     if (socket < 0)
       
   175         qWarning("QSocketNotifier: Invalid socket specified");
       
   176     sockfd = socket;
       
   177     sntype = type;
       
   178     snenabled = true;
       
   179 
       
   180     Q_D(QObject);
       
   181     if (!d->threadData->eventDispatcher) {
       
   182         qWarning("QSocketNotifier: Can only be used with threads started with QThread");
       
   183     } else {
       
   184         d->threadData->eventDispatcher->registerSocketNotifier(this);
       
   185     }
       
   186 }
       
   187 
       
   188 #ifdef QT3_SUPPORT
       
   189 /*!
       
   190     \obsolete
       
   191 
       
   192     Use the QSocketNotifier() constructor combined with the
       
   193     QObject::setObjectName() function instead.
       
   194 
       
   195     \oldcode
       
   196         QSocketNotifier *notifier = new QSocketNotifier(socket, type, parent, name);
       
   197     \newcode
       
   198         QSocketNotifier *notifier = new QSocketNotifier(socket, type, parent);
       
   199         notifier->setObjectName(name);
       
   200     \endcode
       
   201 */
       
   202 
       
   203 QSocketNotifier::QSocketNotifier(int socket, Type type, QObject *parent,
       
   204                                   const char *name)
       
   205     : QObject(parent)
       
   206 {
       
   207     setObjectName(QString::fromAscii(name));
       
   208     if (socket < 0)
       
   209         qWarning("QSocketNotifier: Invalid socket specified");
       
   210     sockfd = socket;
       
   211     sntype = type;
       
   212     snenabled = true;
       
   213 
       
   214     Q_D(QObject);
       
   215     if (!d->threadData->eventDispatcher) {
       
   216         qWarning("QSocketNotifier: Can only be used with threads started with QThread");
       
   217     } else {
       
   218         d->threadData->eventDispatcher->registerSocketNotifier(this);
       
   219     }
       
   220 }
       
   221 #endif
       
   222 /*!
       
   223     Destroys this socket notifier.
       
   224 */
       
   225 
       
   226 QSocketNotifier::~QSocketNotifier()
       
   227 {
       
   228     setEnabled(false);
       
   229 }
       
   230 
       
   231 
       
   232 /*!
       
   233     \fn void QSocketNotifier::activated(int socket)
       
   234 
       
   235     This signal is emitted whenever the socket notifier is enabled and
       
   236     a socket event corresponding to its \l {Type}{type} occurs.
       
   237 
       
   238     The socket identifier is passed in the \a socket parameter.
       
   239 
       
   240     \sa type(), socket()
       
   241 */
       
   242 
       
   243 
       
   244 /*!
       
   245     \fn int QSocketNotifier::socket() const
       
   246 
       
   247     Returns the socket identifier specified to the constructor.
       
   248 
       
   249     \sa type()
       
   250 */
       
   251 
       
   252 /*!
       
   253     \fn Type QSocketNotifier::type() const
       
   254 
       
   255     Returns the socket event type specified to the constructor.
       
   256 
       
   257     \sa socket()
       
   258 */
       
   259 
       
   260 
       
   261 /*!
       
   262     \fn bool QSocketNotifier::isEnabled() const
       
   263 
       
   264     Returns true if the notifier is enabled; otherwise returns false.
       
   265 
       
   266     \sa setEnabled()
       
   267 */
       
   268 
       
   269 /*!
       
   270     If \a enable is true, the notifier is enabled; otherwise the notifier
       
   271     is disabled.
       
   272 
       
   273     The notifier is enabled by default, i.e. it emits the activated()
       
   274     signal whenever a socket event corresponding to its
       
   275     \l{type()}{type} occurs. If it is disabled, it ignores socket
       
   276     events (the same effect as not creating the socket notifier).
       
   277 
       
   278     Write notifiers should normally be disabled immediately after the
       
   279     activated() signal has been emitted
       
   280 
       
   281     \sa isEnabled(), activated()
       
   282 */
       
   283 
       
   284 void QSocketNotifier::setEnabled(bool enable)
       
   285 {
       
   286     if (sockfd < 0)
       
   287         return;
       
   288     if (snenabled == enable)                        // no change
       
   289         return;
       
   290     snenabled = enable;
       
   291 
       
   292     Q_D(QObject);
       
   293     if (!d->threadData->eventDispatcher) // perhaps application/thread is shutting down
       
   294         return;
       
   295     if (snenabled)
       
   296         d->threadData->eventDispatcher->registerSocketNotifier(this);
       
   297     else
       
   298         d->threadData->eventDispatcher->unregisterSocketNotifier(this);
       
   299 }
       
   300 
       
   301 
       
   302 /*!\reimp
       
   303 */
       
   304 bool QSocketNotifier::event(QEvent *e)
       
   305 {
       
   306     // Emits the activated() signal when a QEvent::SockAct is
       
   307     // received.
       
   308     if (e->type() == QEvent::ThreadChange) {
       
   309         if (snenabled) {
       
   310             QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
       
   311                                       Q_ARG(bool, snenabled));
       
   312             setEnabled(false);
       
   313         }
       
   314     }
       
   315     QObject::event(e);                        // will activate filters
       
   316     if (e->type() == QEvent::SockAct) {
       
   317         emit activated(sockfd);
       
   318         return true;
       
   319     }
       
   320     return false;
       
   321 }
       
   322 
       
   323 QT_END_NAMESPACE