reSIProcate/rutil  9694
RWMutex.cxx
Go to the documentation of this file.
00001 /* ====================================================================
00002  * The Vovida Software License, Version 1.0
00003  *
00004  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in
00015  *    the documentation and/or other materials provided with the
00016  *    distribution.
00017  *
00018  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00019  *    and "Vovida Open Communication Application Library (VOCAL)" must
00020  *    not be used to endorse or promote products derived from this
00021  *    software without prior written permission. For written
00022  *    permission, please contact vocal@vovida.org.
00023  *
00024  * 4. Products derived from this software may not be called "VOCAL", nor
00025  *    may "VOCAL" appear in their name, without prior written
00026  *    permission of Vovida Networks, Inc.
00027  *
00028  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00029  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00030  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00031  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00032  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00033  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00034  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00035  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00036  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00037  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00038  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00039  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00040  * DAMAGE.
00041  *
00042  * ====================================================================
00043  *
00044  * This software consists of voluntary contributions made by Vovida
00045  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00046  * Inc.  For more information on Vovida Networks, Inc., please see
00047  * <http://www.vovida.org/>.
00048  *
00049  */
00050 
00051 #include "RWMutex.hxx"
00052 #include "Lock.hxx"
00053 #include <cassert>
00054 
00055 using resip::RWMutex;
00056 using resip::Lock;
00057 
00058 RWMutex::RWMutex()
00059    :   Lockable(),
00060        mReaderCount(0),
00061        mWriterHasLock(false),
00062        mPendingWriterCount(0)
00063 {
00064 }
00065 
00066 
00067 RWMutex::~RWMutex()
00068 {
00069 }
00070 
00071 
00072 void
00073 RWMutex::readlock()
00074 {
00075    Lock    lock(mMutex);
00076 
00077    while ( mWriterHasLock || mPendingWriterCount > 0 )
00078    {
00079       mReadCondition.wait(mMutex);
00080    }
00081 
00082    mReaderCount++;
00083 }
00084 
00085 
00086 void
00087 RWMutex::writelock()
00088 {
00089    Lock    lock(mMutex);
00090 
00091    mPendingWriterCount++;
00092 
00093    while ( mWriterHasLock || mReaderCount > 0 )
00094    {
00095       mPendingWriteCondition.wait(mMutex);
00096    }
00097 
00098    mPendingWriterCount--;
00099 
00100    mWriterHasLock = true;
00101 }
00102 
00103 
00104 void
00105 RWMutex::lock()
00106 {
00107    writelock();
00108 }
00109 
00110 
00111 void
00112 RWMutex::unlock()
00113 {
00114    Lock    lock(mMutex);
00115 
00116    // Unlocking a write lock.
00117    //
00118    if ( mWriterHasLock )
00119    {
00120       assert( mReaderCount == 0 );
00121 
00122       mWriterHasLock = false;
00123 
00124       // Pending writers have priority. Could potentially starve readers.
00125       //
00126       if ( mPendingWriterCount > 0 )
00127       {
00128          mPendingWriteCondition.signal();
00129       }
00130 
00131       // No writer, no pending writers, so all the readers can go.
00132       //
00133       else
00134       {
00135          mReadCondition.broadcast();
00136       }
00137 
00138    }
00139 
00140    // Unlocking a read lock.
00141    //
00142    else
00143    {
00144       assert( mReaderCount > 0 );
00145 
00146       mReaderCount--;
00147 
00148       if ( mReaderCount == 0 && mPendingWriterCount > 0 )
00149       {
00150          mPendingWriteCondition.signal();
00151       }
00152    }
00153 }
00154 
00155 unsigned int
00156 RWMutex::readerCount() const
00157 {
00158    return ( mReaderCount );
00159 }
00160 
00161 unsigned int
00162 RWMutex::pendingWriterCount() const
00163 {
00164    return ( mPendingWriterCount );
00165 }