src/qt3support/tools/q3semaphore.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 Qt3Support 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 "q3semaphore.h"
       
    43 
       
    44 #include "qmutex.h"
       
    45 #include "qwaitcondition.h"
       
    46 
       
    47 QT_BEGIN_NAMESPACE
       
    48 
       
    49 /*!
       
    50     \class Q3Semaphore
       
    51     \threadsafe
       
    52     \brief The Q3Semaphore class provides a robust integer semaphore.
       
    53 
       
    54     \compat
       
    55 
       
    56     A Q3Semaphore can be used to serialize thread execution, in a
       
    57     similar way to a QMutex. A semaphore differs from a mutex, in
       
    58     that a semaphore can be accessed by more than one thread at a
       
    59     time.
       
    60 
       
    61     For example, suppose we have an application that stores data in a
       
    62     large tree structure. The application creates 10 threads
       
    63     (commonly called a thread pool) to perform searches on the tree.
       
    64     When the application searches the tree for some piece of data, it
       
    65     uses one thread per base node to do the searching. A semaphore
       
    66     could be used to make sure that two threads don't try to search
       
    67     the same branch of the tree at the same time.
       
    68 
       
    69     A non-computing example of a semaphore would be dining at a
       
    70     restaurant. A semaphore is initialized to have a maximum count
       
    71     equal to the number of chairs in the restaurant. As people
       
    72     arrive, they want a seat. As seats are filled, the semaphore is
       
    73     accessed, once per person. As people leave, the access is
       
    74     released, allowing more people to enter. If a party of 10 people
       
    75     want to be seated, but there are only 9 seats, those 10 people
       
    76     will wait, but a party of 4 people would be seated (taking the
       
    77     available seats to 5, making the party of 10 people wait longer).
       
    78 
       
    79     When a semaphore is created it is given a number which is the
       
    80     maximum number of concurrent accesses it will permit. This amount
       
    81     may be changed using operator++(), operator--(), operator+=() and
       
    82     operator-=(). The number of accesses allowed is retrieved with
       
    83     available(), and the total number with total(). Note that the
       
    84     incrementing functions will block if there aren't enough available
       
    85     accesses. Use tryAccess() if you want to acquire accesses without
       
    86     blocking.
       
    87 */
       
    88 
       
    89 #ifdef max
       
    90 #undef max
       
    91 #endif
       
    92 
       
    93 class Q3SemaphorePrivate {
       
    94 public:
       
    95     Q3SemaphorePrivate(int);
       
    96 
       
    97     QMutex mutex;
       
    98     QWaitCondition cond;
       
    99 
       
   100     int value, max;
       
   101 };
       
   102 
       
   103 
       
   104 Q3SemaphorePrivate::Q3SemaphorePrivate(int m)
       
   105     : value(0), max(m)
       
   106 {
       
   107 }
       
   108 
       
   109 
       
   110 /*!
       
   111     Creates a new semaphore. The semaphore can be concurrently
       
   112     accessed at most \a maxcount times.
       
   113 */
       
   114 Q3Semaphore::Q3Semaphore(int maxcount)
       
   115 {
       
   116     d = new Q3SemaphorePrivate(maxcount);
       
   117 }
       
   118 
       
   119 
       
   120 /*!
       
   121     Destroys the semaphore.
       
   122 
       
   123     \warning If you destroy a semaphore that has accesses in use the
       
   124     resultant behavior is undefined.
       
   125 */
       
   126 Q3Semaphore::~Q3Semaphore()
       
   127 {
       
   128     delete d;
       
   129 }
       
   130 
       
   131 
       
   132 /*!
       
   133     Postfix ++ operator.
       
   134 
       
   135     Try to get access to the semaphore. If \l available() == 0, this
       
   136     call will block until it can get access, i.e. until available() \>
       
   137     0.
       
   138 */
       
   139 int Q3Semaphore::operator++(int)
       
   140 {
       
   141     QMutexLocker locker(&d->mutex);
       
   142     while (d->value >= d->max)
       
   143         d->cond.wait(locker.mutex());
       
   144 
       
   145     ++d->value;
       
   146     if (d->value > d->max)
       
   147         d->value = d->max;
       
   148 
       
   149     return d->value;
       
   150 }
       
   151 
       
   152 
       
   153 /*!
       
   154     Postfix -- operator.
       
   155 
       
   156     Release access of the semaphore. This wakes all threads waiting
       
   157     for access to the semaphore.
       
   158 */
       
   159 int Q3Semaphore::operator--(int)
       
   160 {
       
   161     QMutexLocker locker(&d->mutex);
       
   162 
       
   163     --d->value;
       
   164     if (d->value < 0)
       
   165         d->value = 0;
       
   166 
       
   167     d->cond.wakeAll();
       
   168 
       
   169     return d->value;
       
   170 }
       
   171 
       
   172 
       
   173 /*!
       
   174     Try to get access to the semaphore. If \l available() \< \a n, this
       
   175     call will block until it can get all the accesses it wants, i.e.
       
   176     until available() \>= \a n.
       
   177 */
       
   178 int Q3Semaphore::operator+=(int n)
       
   179 {
       
   180     QMutexLocker locker(&d->mutex);
       
   181 
       
   182     if (n < 0 || n > d->max) {
       
   183         qWarning("Q3Semaphore::operator+=: parameter %d out of range", n);
       
   184         n = n < 0 ? 0 : d->max;
       
   185     }
       
   186 
       
   187     while (d->value + n > d->max)
       
   188         d->cond.wait(locker.mutex());
       
   189 
       
   190     d->value += n;
       
   191 
       
   192     return d->value;
       
   193 }
       
   194 
       
   195 
       
   196 /*!
       
   197     Release \a n accesses to the semaphore.
       
   198 */
       
   199 int Q3Semaphore::operator-=(int n)
       
   200 {
       
   201     QMutexLocker locker(&d->mutex);
       
   202 
       
   203     if (n < 0 || n > d->value) {
       
   204         qWarning("Q3Semaphore::operator-=: parameter %d out of range", n);
       
   205         n = n < 0 ? 0 : d->value;
       
   206     }
       
   207 
       
   208     d->value -= n;
       
   209     d->cond.wakeAll();
       
   210 
       
   211     return d->value;
       
   212 }
       
   213 
       
   214 
       
   215 /*!
       
   216     Returns the number of accesses currently available to the
       
   217     semaphore.
       
   218 */
       
   219 int Q3Semaphore::available() const
       
   220 {
       
   221     QMutexLocker locker(&d->mutex);
       
   222     return d->max - d->value;
       
   223 }
       
   224 
       
   225 
       
   226 /*!
       
   227     Returns the total number of accesses to the semaphore.
       
   228 */
       
   229 int Q3Semaphore::total() const
       
   230 {
       
   231     QMutexLocker locker(&d->mutex);
       
   232     return d->max;
       
   233 }
       
   234 
       
   235 
       
   236 /*!
       
   237     Try to get access to the semaphore. If \l available() \< \a n, this
       
   238     function will return false immediately. If \l available() \>= \a n,
       
   239     this function will take \a n accesses and return true. This
       
   240     function does \e not block.
       
   241 */
       
   242 bool Q3Semaphore::tryAccess(int n)
       
   243 {
       
   244     QMutexLocker locker(&d->mutex);
       
   245 
       
   246     if (d->value + n > d->max)
       
   247         return false;
       
   248 
       
   249     d->value += n;
       
   250 
       
   251     return true;
       
   252 }
       
   253 
       
   254 QT_END_NAMESPACE