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.2 2010/05/26 01:21:33 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 /*
00057  *   NewThreads is Copyright 1992, 1993, 1994, 1995, 1996, 1997 by:
00058  *
00059  *    Josef Burger    <bolo@cs.wisc.edu>
00060  *    Dylan McNamee    <dylan@cse.ogi.edu>
00061  *      Ed Felten       <felten@cs.princeton.edu>
00062  *
00063  *   All Rights Reserved.
00064  *
00065  *   NewThreads may be freely used as long as credit is given
00066  *   to the above authors and the above copyright is maintained.
00067  */
00068 
00069 /*
00070  * The base thread functionality of Shore Threads is derived
00071  * from the NewThreads implementation wrapped up as c++ objects.
00072  */
00073 
00074 #ifndef SRWLOCK_H
00075 #define SRWLOCK_H
00076 
00077 class mcs_rwlock; // forward
00078 typedef mcs_rwlock srwlock_t;
00079 
00080 
00081 /**\brief "Shore read-write lock:: many-reader/one-writer spin lock 
00082  *
00083  * This read-write lock is implemented around a queue-based lock. It is
00084  * the basis for latches in the storage manager.
00085  *
00086  * Use this to protect data structures that get constantly hammered by
00087  * short reads, and less frequently (but still often) by short writes.
00088  *
00089  * "Short" is the key word here, since this is spin-based.
00090  */
00091 class mcs_rwlock : protected queue_based_lock_t 
00092 {
00093     typedef queue_based_lock_t parent_lock;
00094     
00095     /* \todo  TODO: Add support for blocking if any of the spins takes too long.
00096      * 
00097        There are three spins to worry about: spin_on_writer,
00098        spin_on_reader, and spin_on_waiting
00099 
00100        The overall idea is that threads which decide to block lose
00101        their place in line to avoid forming convoys. To make this work
00102        we need to modify the spin_on_waiting so that it blocks
00103        eventually; the mcs_lock's preemption resistance will take care
00104        of booting it from the queue as necessary.
00105 
00106        Whenever the last reader leaves it signals a cond var; when a
00107        writer leaves it broadcasts.
00108        END TODO
00109      */
00110     unsigned int volatile _holders; // 2*readers + writer
00111 
00112 public:
00113     enum rwmode_t { NONE=0, WRITER=0x1, READER=0x2 };
00114     mcs_rwlock() : _holders(0) { }
00115     ~mcs_rwlock() {}
00116 
00117     /// Return the mode in which this lock is held by anyone.
00118     rwmode_t mode() const { int holders = *&_holders; 
00119         return (holders == WRITER)? WRITER : (holders > 0) ? READER : NONE; }
00120 
00121     /// True if locked in any mode.
00122     bool is_locked() const { return (*&_holders)==0?false:true; }
00123 
00124     /// 1 if held in write mode, else it's the number of readers
00125     int num_holders() const { int holders = *&_holders; 
00126                               return (holders == WRITER)? 1 : holders/2; }
00127 
00128     /// True iff has one or more readers.
00129     bool has_reader() const { return *&_holders & ~WRITER; }
00130     /// True iff has a writer (never more than 1) 
00131     bool has_writer() const { return *&_holders & WRITER; }
00132 
00133     /// True if success.
00134     bool attempt_read();
00135     /// Wait (spin) until acquired.
00136     void acquire_read();
00137     /// This thread had better hold the lock in read mode.
00138     void release_read();
00139 
00140     /// True if success.
00141     bool attempt_write();
00142     /// Wait (spin) until acquired.
00143     void acquire_write();
00144     /// This thread had better hold the lock in write mode.
00145     void release_write();
00146     /// Try to upgrade from READ to WRITE mode. Fail if any other threads are waiting.
00147     bool attempt_upgrade();
00148     /// Atomically downgrade the lock from WRITE to READ mode.
00149     void downgrade();
00150 
00151 private:
00152     // CC mangles this as __1cKmcs_rwlockO_spin_on_writer6M_v_
00153     void _spin_on_writer();
00154     // CC mangles this as __1cKmcs_rwlockP_spin_on_readers6M_v_
00155     void _spin_on_readers();
00156     bool _attempt_write(unsigned int expected);
00157     void _add_when_writer_leaves(int delta);
00158 };
00159 
00160 /*<std-footer incl-file-exclusion='STHREAD_H'>  -- do not edit anything below this line -- */
00161 
00162 #endif          /*</std-footer>*/

Generated on Wed Jul 7 17:22:32 2010 for Shore Storage Manager by  doxygen 1.4.7