spin_rw_mutex.h

00001 /*
00002     Copyright 2005-2011 Intel Corporation.  All Rights Reserved.
00003 
00004     The source code contained or described herein and all documents related
00005     to the source code ("Material") are owned by Intel Corporation or its
00006     suppliers or licensors.  Title to the Material remains with Intel
00007     Corporation or its suppliers and licensors.  The Material is protected
00008     by worldwide copyright laws and treaty provisions.  No part of the
00009     Material may be used, copied, reproduced, modified, published, uploaded,
00010     posted, transmitted, distributed, or disclosed in any way without
00011     Intel's prior express written permission.
00012 
00013     No license under any patent, copyright, trade secret or other
00014     intellectual property right is granted to or conferred upon you by
00015     disclosure or delivery of the Materials, either expressly, by
00016     implication, inducement, estoppel or otherwise.  Any license under such
00017     intellectual property rights must be express and approved by Intel in
00018     writing.
00019 */
00020 
00021 #ifndef __TBB_spin_rw_mutex_H
00022 #define __TBB_spin_rw_mutex_H
00023 
00024 #include "tbb_stddef.h"
00025 #include "tbb_machine.h"
00026 #include "tbb_profiling.h"
00027 
00028 namespace tbb {
00029 
00030 class spin_rw_mutex_v3;
00031 typedef spin_rw_mutex_v3 spin_rw_mutex;
00032 
00034 
00035 class spin_rw_mutex_v3 {
00037 
00039     bool __TBB_EXPORTED_METHOD internal_acquire_writer();
00040 
00042 
00043     void __TBB_EXPORTED_METHOD internal_release_writer();
00044 
00046     void __TBB_EXPORTED_METHOD internal_acquire_reader();
00047 
00049     bool __TBB_EXPORTED_METHOD internal_upgrade();
00050 
00052 
00053     void __TBB_EXPORTED_METHOD internal_downgrade();
00054 
00056     void __TBB_EXPORTED_METHOD internal_release_reader();
00057 
00059     bool __TBB_EXPORTED_METHOD internal_try_acquire_writer();
00060 
00062     bool __TBB_EXPORTED_METHOD internal_try_acquire_reader();
00063 
00065 public:
00067     spin_rw_mutex_v3() : state(0) {
00068 #if TBB_USE_THREADING_TOOLS
00069         internal_construct();
00070 #endif
00071     }
00072 
00073 #if TBB_USE_ASSERT
00075     ~spin_rw_mutex_v3() {
00076         __TBB_ASSERT( !state, "destruction of an acquired mutex");
00077     };
00078 #endif /* TBB_USE_ASSERT */
00079 
00081 
00083     class scoped_lock : internal::no_copy {
00084     public:
00086 
00087         scoped_lock() : mutex(NULL), is_writer(false) {}
00088 
00090         scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
00091             acquire(m, write);
00092         }
00093 
00095         ~scoped_lock() {
00096             if( mutex ) release();
00097         }
00098 
00100         void acquire( spin_rw_mutex& m, bool write = true ) {
00101             __TBB_ASSERT( !mutex, "holding mutex already" );
00102             is_writer = write; 
00103             mutex = &m;
00104             if( write ) mutex->internal_acquire_writer();
00105             else        mutex->internal_acquire_reader();
00106         }
00107 
00109 
00110         bool upgrade_to_writer() {
00111             __TBB_ASSERT( mutex, "lock is not acquired" );
00112             __TBB_ASSERT( !is_writer, "not a reader" );
00113             is_writer = true; 
00114             return mutex->internal_upgrade();
00115         }
00116 
00118         void release() {
00119             __TBB_ASSERT( mutex, "lock is not acquired" );
00120             spin_rw_mutex *m = mutex; 
00121             mutex = NULL;
00122 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00123             if( is_writer ) m->internal_release_writer();
00124             else            m->internal_release_reader();
00125 #else
00126             if( is_writer ) __TBB_AtomicAND( &m->state, READERS ); 
00127             else            __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
00128 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00129         }
00130 
00132         bool downgrade_to_reader() {
00133 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00134             __TBB_ASSERT( mutex, "lock is not acquired" );
00135             __TBB_ASSERT( is_writer, "not a writer" );
00136             mutex->internal_downgrade();
00137 #else
00138             __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
00139 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00140             is_writer = false;
00141 
00142             return true;
00143         }
00144 
00146         bool try_acquire( spin_rw_mutex& m, bool write = true ) {
00147             __TBB_ASSERT( !mutex, "holding mutex already" );
00148             bool result;
00149             is_writer = write; 
00150             result = write? m.internal_try_acquire_writer()
00151                           : m.internal_try_acquire_reader();
00152             if( result ) 
00153                 mutex = &m;
00154             return result;
00155         }
00156 
00157     protected:
00159         spin_rw_mutex* mutex;
00160 
00162 
00163         bool is_writer;
00164     };
00165 
00166     // Mutex traits
00167     static const bool is_rw_mutex = true;
00168     static const bool is_recursive_mutex = false;
00169     static const bool is_fair_mutex = false;
00170 
00171     // ISO C++0x compatibility methods
00172 
00174     void lock() {internal_acquire_writer();}
00175 
00177 
00178     bool try_lock() {return internal_try_acquire_writer();}
00179 
00181     void unlock() {
00182 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00183         if( state&WRITER ) internal_release_writer();
00184         else               internal_release_reader();
00185 #else
00186         if( state&WRITER ) __TBB_AtomicAND( &state, READERS ); 
00187         else               __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
00188 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00189     }
00190 
00191     // Methods for reader locks that resemble ISO C++0x compatibility methods.
00192 
00194     void lock_read() {internal_acquire_reader();}
00195 
00197 
00198     bool try_lock_read() {return internal_try_acquire_reader();}
00199 
00200 private:
00201     typedef intptr_t state_t;
00202     static const state_t WRITER = 1;
00203     static const state_t WRITER_PENDING = 2;
00204     static const state_t READERS = ~(WRITER | WRITER_PENDING);
00205     static const state_t ONE_READER = 4;
00206     static const state_t BUSY = WRITER | READERS;
00208 
00211     state_t state;
00212 
00213     void __TBB_EXPORTED_METHOD internal_construct();
00214 };
00215 
00216 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
00217 
00218 } // namespace tbb
00219 
00220 #endif /* __TBB_spin_rw_mutex_H */

Copyright © 2005-2011 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.