srwlock.h

00001 /* -*- mode:C++; c-basic-offset:4 -*-
00002      Shore-MT -- Multi-threaded port of the SHORE storage manager
00003    
00004                        Copyright (c) 2007-2009
00005       Data Intensive Applications and Systems Labaratory (DIAS)
00006                Ecole Polytechnique Federale de Lausanne
00007    
00008                          All Rights Reserved.
00009    
00010    Permission to use, copy, modify and distribute this software and
00011    its documentation is hereby granted, provided that both the
00012    copyright notice and this permission notice appear in all copies of
00013    the software, derivative works or modified versions, and any
00014    portions thereof, and that both notices appear in supporting
00015    documentation.
00016    
00017    This code is distributed in the hope that it will be useful, but
00018    WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
00020    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
00021    RESULTING FROM THE USE OF THIS SOFTWARE.
00022 */
00023 
00024 // -*- mode:c++; c-basic-offset:4 -*-
00025 /*<std-header orig-src='shore' incl-file-exclusion='STHREAD_H'>
00026 
00027  $Id: srwlock.h,v 1.4 2010/11/08 15:07:28 nhall Exp $
00028 
00029 SHORE -- Scalable Heterogeneous Object REpository
00030 
00031 Copyright (c) 1994-99 Computer Sciences Department, University of
00032                       Wisconsin -- Madison
00033 All Rights Reserved.
00034 
00035 Permission to use, copy, modify and distribute this software and its
00036 documentation is hereby granted, provided that both the copyright
00037 notice and this permission notice appear in all copies of the
00038 software, derivative works or modified versions, and any portions
00039 thereof, and that both notices appear in supporting documentation.
00040 
00041 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00042 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00043 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00044 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00045 
00046 This software was developed with support by the Advanced Research
00047 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00048 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00049 Further funding for this work was provided by DARPA through
00050 Rome Research Laboratory Contract No. F30602-97-2-0247.
00051 
00052 */
00053 
00054 /*  -- do not edit anything above this line --   </std-header>*/
00055 
00056 #ifndef SRWLOCK_H
00057 #define SRWLOCK_H
00058 
00059 class mcs_rwlock; // forward
00060 typedef mcs_rwlock srwlock_t;
00061 
00062 
00063 /**\brief "Shore read-write lock:: many-reader/one-writer spin lock 
00064  *
00065  * This read-write lock is implemented around a queue-based lock. It is
00066  * the basis for latches in the storage manager.
00067  *
00068  * Use this to protect data structures that get constantly hammered by
00069  * short reads, and less frequently (but still often) by short writes.
00070  *
00071  * "Short" is the key word here, since this is spin-based.
00072  */
00073 class mcs_rwlock : protected queue_based_lock_t 
00074 {
00075     typedef queue_based_lock_t parent_lock;
00076     
00077     /* \todo  TODO: Add support for blocking if any of the spins takes too long.
00078      * 
00079        There are three spins to worry about: spin_on_writer,
00080        spin_on_reader, and spin_on_waiting
00081 
00082        The overall idea is that threads which decide to block lose
00083        their place in line to avoid forming convoys. To make this work
00084        we need to modify the spin_on_waiting so that it blocks
00085        eventually; the mcs_lock's preemption resistance will take care
00086        of booting it from the queue as necessary.
00087 
00088        Whenever the last reader leaves it signals a cond var; when a
00089        writer leaves it broadcasts.
00090        END TODO
00091      */
00092     unsigned int volatile _holders; // 2*readers + writer
00093 
00094 public:
00095     enum rwmode_t { NONE=0, WRITER=0x1, READER=0x2 };
00096     mcs_rwlock() : _holders(0) { }
00097     ~mcs_rwlock() {}
00098 
00099     /// Return the mode in which this lock is held by anyone.
00100     rwmode_t mode() const { int holders = *&_holders; 
00101         return (holders == WRITER)? WRITER : (holders > 0) ? READER : NONE; }
00102 
00103     /// True if locked in any mode.
00104     bool is_locked() const { return (*&_holders)==0?false:true; }
00105 
00106     /// 1 if held in write mode, else it's the number of readers
00107     int num_holders() const { int holders = *&_holders; 
00108                               return (holders == WRITER)? 1 : holders/2; }
00109 
00110     /// True iff has one or more readers.
00111     bool has_reader() const { return *&_holders & ~WRITER; }
00112     /// True iff has a writer (never more than 1) 
00113     bool has_writer() const { return *&_holders & WRITER; }
00114 
00115     /// True if success.
00116     bool attempt_read();
00117     /// Wait (spin) until acquired.
00118     void acquire_read();
00119     /// This thread had better hold the lock in read mode.
00120     void release_read();
00121 
00122     /// True if success.
00123     bool attempt_write();
00124     /// Wait (spin) until acquired.
00125     void acquire_write();
00126     /// This thread had better hold the lock in write mode.
00127     void release_write();
00128     /// Try to upgrade from READ to WRITE mode. Fail if any other threads are waiting.
00129     bool attempt_upgrade();
00130     /// Atomically downgrade the lock from WRITE to READ mode.
00131     void downgrade();
00132 
00133 private:
00134     // CC mangles this as __1cKmcs_rwlockO_spin_on_writer6M_v_
00135     int  _spin_on_writer();
00136     // CC mangles this as __1cKmcs_rwlockP_spin_on_readers6M_v_
00137     void _spin_on_readers();
00138     bool _attempt_write(unsigned int expected);
00139     void _add_when_writer_leaves(int delta);
00140 };
00141 
00142 /*<std-footer incl-file-exclusion='STHREAD_H'>  -- do not edit anything below this line -- */
00143 
00144 #endif          /*</std-footer>*/

Generated on Mon Jan 2 15:13:57 2012 for Shore Storage Manager by  doxygen 1.4.7