spin_rw_mutex.h

00001 /*
00002     Copyright 2005-2009 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 
00091         scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
00092             acquire(m, write);
00093         }
00094 
00096         ~scoped_lock() {
00097             if( mutex ) release();
00098         }
00099 
00101         void acquire( spin_rw_mutex& m, bool write = true ) {
00102             __TBB_ASSERT( !mutex, "holding mutex already" );
00103             is_writer = write; 
00104             mutex = &m;
00105             if( write ) mutex->internal_acquire_writer();
00106             else        mutex->internal_acquire_reader();
00107         }
00108 
00110 
00111         bool upgrade_to_writer() {
00112             __TBB_ASSERT( mutex, "lock is not acquired" );
00113             __TBB_ASSERT( !is_writer, "not a reader" );
00114             is_writer = true; 
00115             return mutex->internal_upgrade();
00116         }
00117 
00119         void release() {
00120             __TBB_ASSERT( mutex, "lock is not acquired" );
00121             spin_rw_mutex *m = mutex; 
00122             mutex = NULL;
00123 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00124             if( is_writer ) m->internal_release_writer();
00125             else            m->internal_release_reader();
00126 #else
00127             if( is_writer ) __TBB_AtomicAND( &m->state, READERS ); 
00128             else            __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
00129 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00130         }
00131 
00133         bool downgrade_to_reader() {
00134 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00135             __TBB_ASSERT( mutex, "lock is not acquired" );
00136             __TBB_ASSERT( is_writer, "not a writer" );
00137             mutex->internal_downgrade();
00138 #else
00139             __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
00140 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00141             is_writer = false;
00142 
00143             return true;
00144         }
00145 
00147         bool try_acquire( spin_rw_mutex& m, bool write = true ) {
00148             __TBB_ASSERT( !mutex, "holding mutex already" );
00149             bool result;
00150             is_writer = write; 
00151             result = write? m.internal_try_acquire_writer()
00152                           : m.internal_try_acquire_reader();
00153             if( result ) 
00154                 mutex = &m;
00155             return result;
00156         }
00157 
00158     private:
00160         spin_rw_mutex* mutex;
00161 
00163 
00164         bool is_writer;
00165     };
00166 
00167     // Mutex traits
00168     static const bool is_rw_mutex = true;
00169     static const bool is_recursive_mutex = false;
00170     static const bool is_fair_mutex = false;
00171 
00172     // ISO C++0x compatibility methods
00173 
00175     void lock() {internal_acquire_writer();}
00176 
00178 
00179     bool try_lock() {return internal_try_acquire_writer();}
00180 
00182     void unlock() {
00183 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00184         if( state&WRITER ) internal_release_writer();
00185         else               internal_release_reader();
00186 #else
00187         if( state&WRITER ) __TBB_AtomicAND( &state, READERS ); 
00188         else               __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
00189 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00190     }
00191 
00192     // Methods for reader locks that resemble ISO C++0x compatibility methods.
00193 
00195     void lock_read() {internal_acquire_reader();}
00196 
00198 
00199     bool try_lock_read() {return internal_try_acquire_reader();}
00200 
00201 private:
00202     typedef intptr_t state_t;
00203     static const state_t WRITER = 1;
00204     static const state_t WRITER_PENDING = 2;
00205     static const state_t READERS = ~(WRITER | WRITER_PENDING);
00206     static const state_t ONE_READER = 4;
00207     static const state_t BUSY = WRITER | READERS;
00209 
00212     state_t state;
00213 
00214     void __TBB_EXPORTED_METHOD internal_construct();
00215 };
00216 
00217 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
00218 
00219 } // namespace tbb
00220 
00221 #endif /* __TBB_spin_rw_mutex_H */

Copyright © 2005-2009 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.