doc/src/examples/semaphores.qdoc
branchRCL_3
changeset 8 3f74d0d4af4c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/examples/semaphores.qdoc	Thu Apr 08 14:19:33 2010 +0300
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \example threads/semaphores
+    \title Semaphores Example
+
+    The Semaphores example shows how to use QSemaphore to control
+    access to a circular buffer shared by a producer thread and a
+    consumer thread.
+
+    The producer writes data to the buffer until it reaches the end
+    of the buffer, at which point it restarts from the beginning,
+    overwriting existing data. The consumer thread reads the data as
+    it is produced and writes it to standard error.
+
+    Semaphores make it possible to have a higher level of concurrency
+    than mutexes. If accesses to the buffer were guarded by a QMutex,
+    the consumer thread couldn't access the buffer at the same time
+    as the producer thread. Yet, there is no harm in having both
+    threads working on \e{different parts} of the buffer at the same
+    time.
+
+    The example comprises two classes: \c Producer and \c Consumer.
+    Both inherit from QThread. The circular buffer used for
+    communicating between these two classes and the semaphores that
+    protect it are global variables.
+
+    An alternative to using QSemaphore to solve the producer-consumer
+    problem is to use QWaitCondition and QMutex. This is what the
+    \l{threads/waitconditions}{Wait Conditions} example does.
+
+    \section1 Global Variables
+
+    Let's start by reviewing the circular buffer and the associated
+    semaphores:
+
+    \snippet examples/threads/semaphores/semaphores.cpp 0
+
+    \c DataSize is the amout of data that the producer will generate.
+    To keep the example as simple as possible, we make it a constant.
+    \c BufferSize is the size of the circular buffer. It is less than
+    \c DataSize, meaning that at some point the producer will reach
+    the end of the buffer and restart from the beginning.
+
+    To synchronize the producer and the consumer, we need two
+    semaphores. The \c freeBytes semaphore controls the "free" area
+    of the buffer (the area that the producer hasn't filled with data
+    yet or that the consumer has already read). The \c usedBytes
+    semaphore controls the "used" area of the buffer (the area that
+    the producer has filled but that the consumer hasn't read yet).
+
+    Together, the semaphores ensure that the producer is never more
+    than \c BufferSize bytes ahead of the consumer, and that the
+    consumer never reads data that the producer hasn't generated yet.
+
+    The \c freeBytes semaphore is initialized with \c BufferSize,
+    because initially the entire buffer is empty. The \c usedBytes
+    semaphore is initialized to 0 (the default value if none is
+    specified).
+
+    \section1 Producer Class
+
+    Let's review the code for the \c Producer class:
+
+    \snippet examples/threads/semaphores/semaphores.cpp 1
+    \snippet examples/threads/semaphores/semaphores.cpp 2
+
+    The producer generates \c DataSize bytes of data. Before it
+    writes a byte to the circular buffer, it must acquire a "free"
+    byte using the \c freeBytes semaphore. The QSemaphore::acquire()
+    call might block if the consumer hasn't kept up the pace with the
+    producer.
+
+    At the end, the producer releases a byte using the \c usedBytes
+    semaphore. The "free" byte has successfully been transformed into
+    a "used" byte, ready to be read by the consumer.
+
+    \section1 Consumer Class
+
+    Let's now turn to the \c Consumer class:
+
+    \snippet examples/threads/semaphores/semaphores.cpp 3
+    \snippet examples/threads/semaphores/semaphores.cpp 4
+
+    The code is very similar to the producer, except that this time
+    we acquire a "used" byte and release a "free" byte, instead of
+    the opposite.
+
+    \section1 The main() Function
+
+    In \c main(), we create the two threads and call QThread::wait()
+    to ensure that both threads get time to finish before we exit:
+
+    \snippet examples/threads/semaphores/semaphores.cpp 5
+    \snippet examples/threads/semaphores/semaphores.cpp 6
+
+    So what happens when we run the program? Initially, the producer
+    thread is the only one that can do anything; the consumer is
+    blocked waiting for the \c usedBytes semaphore to be released (its
+    initial \l{QSemaphore::available()}{available()} count is 0).
+    Once the producer has put one byte in the buffer,
+    \c{freeBytes.available()} is \c BufferSize - 1 and
+    \c{usedBytes.available()} is 1. At that point, two things can
+    happen: Either the consumer thread takes over and reads that
+    byte, or the consumer gets to produce a second byte.
+
+    The producer-consumer model presented in this example makes it
+    possible to write highly concurrent multithreaded applications.
+    On a multiprocessor machine, the program is potentially up to
+    twice as fast as the equivalent mutex-based program, since the
+    two threads can be active at the same time on different parts of
+    the buffer.
+
+    Be aware though that these benefits aren't always realized.
+    Acquiring and releasing a QSemaphore has a cost. In practice, it
+    would probably be worthwhile to divide the buffer into chunks and
+    to operate on chunks instead of individual bytes. The buffer size
+    is also a parameter that must be selected carefully, based on
+    experimentation.
+*/