blocxx

RWLocker.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2006, Novell, Inc. All rights reserved.
00004 * 
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 * 
00008 *     * Redistributions of source code must retain the above copyright notice,
00009 *       this list of conditions and the following disclaimer.
00010 *     * Redistributions in binary form must reproduce the above copyright
00011 *       notice, this list of conditions and the following disclaimer in the
00012 *       documentation and/or other materials provided with the distribution.
00013 *     * Neither the name of 
00014 *       Vintela, Inc., 
00015 *       nor Novell, Inc., 
00016 *       nor the names of its contributors or employees may be used to 
00017 *       endorse or promote products derived from this software without 
00018 *       specific prior written permission.
00019 * 
00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030 * POSSIBILITY OF SUCH DAMAGE.
00031 *******************************************************************************/
00032 
00033 
00039 #ifndef BLOCXX_RWLOCKER_HPP_INCLUDE_GUARD_
00040 #define BLOCXX_RWLOCKER_HPP_INCLUDE_GUARD_
00041 #include "blocxx/BLOCXX_config.h"
00042 #include "blocxx/GenericRWLockImpl.hpp"
00043 
00044 namespace BLOCXX_NAMESPACE
00045 {
00046 
00047 BLOCXX_DECLARE_APIEXCEPTION(RWLocker, BLOCXX_COMMON_API);
00049 // The locker is recursive and also supports upgrading a read-lock to a write lock
00050 class BLOCXX_COMMON_API RWLocker
00051 {
00052 public:
00053    RWLocker();
00054    ~RWLocker();
00055    
00059    void getReadLock(const Timeout& timeout);
00060    void getReadLock(UInt32 sTimeout, UInt32 usTimeout=0) BLOCXX_DEPRECATED;
00061    
00068    void getWriteLock(const Timeout& timeout);
00069    void getWriteLock(UInt32 sTimeout, UInt32 usTimeout=0) BLOCXX_DEPRECATED;
00070    
00074    void releaseReadLock();
00075    
00079    void releaseWriteLock();
00080 
00081 private:
00082    // Have to do this because on some platforms one thread may have different values for
00083    // a Thread_t, and ThreadImpl::sameThreads() has to be called to know if they refer
00084    // to the same one.
00085    struct ThreadComparer
00086    {
00087       bool operator()(Thread_t x, Thread_t y) const;
00088    };
00089 
00090    GenericRWLockImpl<Thread_t, ThreadComparer> m_impl;
00091 
00092    // unimplemented
00093    RWLocker(const RWLocker&);
00094    RWLocker& operator=(const RWLocker&);
00095 };
00097 class BLOCXX_COMMON_API ReadLock
00098 {
00099 public:
00100    ReadLock(RWLocker& locker, const Timeout& timeout)
00101       : m_locker(&locker)
00102       , m_released(false)
00103    {
00104       m_locker->getReadLock(timeout);
00105    }
00106    ReadLock(RWLocker& locker, UInt32 sTimeout, UInt32 usTimeout=0) BLOCXX_DEPRECATED; // in 4.0.0
00107    ~ReadLock()
00108    {
00109       release();
00110    }
00111    void lock(const Timeout& timeout)
00112    {
00113       if (m_released)
00114       {
00115          m_locker->getReadLock(timeout);
00116          m_released = false;
00117       }
00118    }
00119    BLOCXX_DEPRECATED void lock(UInt32 sTimeout, UInt32 usTimeout=0)
00120    {
00121       if (m_released)
00122       {
00123          m_locker->getReadLock(Timeout::relative(sTimeout + static_cast<float>(usTimeout) * 1000000.0));
00124          m_released = false;
00125       }
00126    }
00127    void release()
00128    {
00129       if (!m_released)
00130       {
00131          m_locker->releaseReadLock();
00132          m_released = true;
00133       }
00134    }
00135 private:
00136    RWLocker* m_locker;
00137    bool m_released;
00138    // noncopyable
00139    ReadLock(const ReadLock&);
00140    ReadLock& operator=(const ReadLock&);
00141 };
00142 
00143 inline
00144 ReadLock::ReadLock(RWLocker& locker, UInt32 sTimeout, UInt32 usTimeout)
00145    : m_locker(&locker)
00146    , m_released(false)
00147 {
00148    m_locker->getReadLock(Timeout::relative(sTimeout + static_cast<float>(usTimeout) * 1000000.0));
00149 } 
00151 class BLOCXX_COMMON_API WriteLock
00152 {
00153 public:
00154    WriteLock(RWLocker& locker, const Timeout& timeout)
00155       : m_locker(&locker)
00156       , m_released(false)
00157    {
00158       m_locker->getWriteLock(timeout);
00159    }
00160    WriteLock(RWLocker& locker, UInt32 sTimeout, UInt32 usTimeout=0) BLOCXX_DEPRECATED; // in 4.0.0
00161    ~WriteLock()
00162    {
00163       release();
00164    }
00165    void lock(const Timeout& timeout)
00166    {
00167       if (m_released)
00168       {
00169          m_locker->getWriteLock(timeout);
00170          m_released = false;
00171       }
00172    }
00173    BLOCXX_DEPRECATED void lock(UInt32 sTimeout, UInt32 usTimeout=0) // in 4.0.0
00174    {
00175       if (m_released)
00176       {
00177          m_locker->getWriteLock(Timeout::relative(sTimeout + static_cast<float>(usTimeout) * 1000000.0));
00178          m_released = false;
00179       }
00180    }
00181    void release()
00182    {
00183       if (!m_released)
00184       {
00185          m_locker->releaseWriteLock();
00186          m_released = true;
00187       }
00188    }
00189 private:
00190    RWLocker* m_locker;
00191    bool m_released;
00192    
00193    // noncopyable
00194    WriteLock(const WriteLock&);
00195    WriteLock& operator=(const WriteLock&);
00196 };
00197 
00198 inline
00199 WriteLock::WriteLock(RWLocker& locker, UInt32 sTimeout, UInt32 usTimeout)
00200    : m_locker(&locker)
00201    , m_released(false)
00202 {
00203    m_locker->getWriteLock(Timeout::relative(sTimeout + static_cast<float>(usTimeout) * 1000000.0));
00204 }
00205 
00206 } // end namespace BLOCXX_NAMESPACE
00207 
00208 #endif