doc/src/examples/semaphores.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
equal deleted inserted replaced
6:dee5afe5301f 7:3f74d0d4af4c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 documentation 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 /*!
       
    43     \example threads/semaphores
       
    44     \title Semaphores Example
       
    45 
       
    46     The Semaphores example shows how to use QSemaphore to control
       
    47     access to a circular buffer shared by a producer thread and a
       
    48     consumer thread.
       
    49 
       
    50     The producer writes data to the buffer until it reaches the end
       
    51     of the buffer, at which point it restarts from the beginning,
       
    52     overwriting existing data. The consumer thread reads the data as
       
    53     it is produced and writes it to standard error.
       
    54 
       
    55     Semaphores make it possible to have a higher level of concurrency
       
    56     than mutexes. If accesses to the buffer were guarded by a QMutex,
       
    57     the consumer thread couldn't access the buffer at the same time
       
    58     as the producer thread. Yet, there is no harm in having both
       
    59     threads working on \e{different parts} of the buffer at the same
       
    60     time.
       
    61 
       
    62     The example comprises two classes: \c Producer and \c Consumer.
       
    63     Both inherit from QThread. The circular buffer used for
       
    64     communicating between these two classes and the semaphores that
       
    65     protect it are global variables.
       
    66 
       
    67     An alternative to using QSemaphore to solve the producer-consumer
       
    68     problem is to use QWaitCondition and QMutex. This is what the
       
    69     \l{threads/waitconditions}{Wait Conditions} example does.
       
    70 
       
    71     \section1 Global Variables
       
    72 
       
    73     Let's start by reviewing the circular buffer and the associated
       
    74     semaphores:
       
    75 
       
    76     \snippet examples/threads/semaphores/semaphores.cpp 0
       
    77 
       
    78     \c DataSize is the amout of data that the producer will generate.
       
    79     To keep the example as simple as possible, we make it a constant.
       
    80     \c BufferSize is the size of the circular buffer. It is less than
       
    81     \c DataSize, meaning that at some point the producer will reach
       
    82     the end of the buffer and restart from the beginning.
       
    83 
       
    84     To synchronize the producer and the consumer, we need two
       
    85     semaphores. The \c freeBytes semaphore controls the "free" area
       
    86     of the buffer (the area that the producer hasn't filled with data
       
    87     yet or that the consumer has already read). The \c usedBytes
       
    88     semaphore controls the "used" area of the buffer (the area that
       
    89     the producer has filled but that the consumer hasn't read yet).
       
    90 
       
    91     Together, the semaphores ensure that the producer is never more
       
    92     than \c BufferSize bytes ahead of the consumer, and that the
       
    93     consumer never reads data that the producer hasn't generated yet.
       
    94 
       
    95     The \c freeBytes semaphore is initialized with \c BufferSize,
       
    96     because initially the entire buffer is empty. The \c usedBytes
       
    97     semaphore is initialized to 0 (the default value if none is
       
    98     specified).
       
    99 
       
   100     \section1 Producer Class
       
   101 
       
   102     Let's review the code for the \c Producer class:
       
   103 
       
   104     \snippet examples/threads/semaphores/semaphores.cpp 1
       
   105     \snippet examples/threads/semaphores/semaphores.cpp 2
       
   106 
       
   107     The producer generates \c DataSize bytes of data. Before it
       
   108     writes a byte to the circular buffer, it must acquire a "free"
       
   109     byte using the \c freeBytes semaphore. The QSemaphore::acquire()
       
   110     call might block if the consumer hasn't kept up the pace with the
       
   111     producer.
       
   112 
       
   113     At the end, the producer releases a byte using the \c usedBytes
       
   114     semaphore. The "free" byte has successfully been transformed into
       
   115     a "used" byte, ready to be read by the consumer.
       
   116 
       
   117     \section1 Consumer Class
       
   118 
       
   119     Let's now turn to the \c Consumer class:
       
   120 
       
   121     \snippet examples/threads/semaphores/semaphores.cpp 3
       
   122     \snippet examples/threads/semaphores/semaphores.cpp 4
       
   123 
       
   124     The code is very similar to the producer, except that this time
       
   125     we acquire a "used" byte and release a "free" byte, instead of
       
   126     the opposite.
       
   127 
       
   128     \section1 The main() Function
       
   129 
       
   130     In \c main(), we create the two threads and call QThread::wait()
       
   131     to ensure that both threads get time to finish before we exit:
       
   132 
       
   133     \snippet examples/threads/semaphores/semaphores.cpp 5
       
   134     \snippet examples/threads/semaphores/semaphores.cpp 6
       
   135 
       
   136     So what happens when we run the program? Initially, the producer
       
   137     thread is the only one that can do anything; the consumer is
       
   138     blocked waiting for the \c usedBytes semaphore to be released (its
       
   139     initial \l{QSemaphore::available()}{available()} count is 0).
       
   140     Once the producer has put one byte in the buffer,
       
   141     \c{freeBytes.available()} is \c BufferSize - 1 and
       
   142     \c{usedBytes.available()} is 1. At that point, two things can
       
   143     happen: Either the consumer thread takes over and reads that
       
   144     byte, or the consumer gets to produce a second byte.
       
   145 
       
   146     The producer-consumer model presented in this example makes it
       
   147     possible to write highly concurrent multithreaded applications.
       
   148     On a multiprocessor machine, the program is potentially up to
       
   149     twice as fast as the equivalent mutex-based program, since the
       
   150     two threads can be active at the same time on different parts of
       
   151     the buffer.
       
   152 
       
   153     Be aware though that these benefits aren't always realized.
       
   154     Acquiring and releasing a QSemaphore has a cost. In practice, it
       
   155     would probably be worthwhile to divide the buffer into chunks and
       
   156     to operate on chunks instead of individual bytes. The buffer size
       
   157     is also a parameter that must be selected carefully, based on
       
   158     experimentation.
       
   159 */