spin_rw_mutex.h

00001 /*
00002     Copyright 2005-2012 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             __TBB_ASSERT( mutex, "lock is not acquired" );
00134             __TBB_ASSERT( is_writer, "not a writer" );
00135 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
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             return true;
00142         }
00143 
00145         bool try_acquire( spin_rw_mutex& m, bool write = true ) {
00146             __TBB_ASSERT( !mutex, "holding mutex already" );
00147             bool result;
00148             is_writer = write; 
00149             result = write? m.internal_try_acquire_writer()
00150                           : m.internal_try_acquire_reader();
00151             if( result ) 
00152                 mutex = &m;
00153             return result;
00154         }
00155 
00156     protected:
00158         spin_rw_mutex* mutex;
00159 
00161 
00162         bool is_writer;
00163     };
00164 
00165     // Mutex traits
00166     static const bool is_rw_mutex = true;
00167     static const bool is_recursive_mutex = false;
00168     static const bool is_fair_mutex = false;
00169 
00170     // ISO C++0x compatibility methods
00171 
00173     void lock() {internal_acquire_writer();}
00174 
00176 
00177     bool try_lock() {return internal_try_acquire_writer();}
00178 
00180     void unlock() {
00181 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00182         if( state&WRITER ) internal_release_writer();
00183         else               internal_release_reader();
00184 #else
00185         if( state&WRITER ) __TBB_AtomicAND( &state, READERS ); 
00186         else               __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
00187 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00188     }
00189 
00190     // Methods for reader locks that resemble ISO C++0x compatibility methods.
00191 
00193     void lock_read() {internal_acquire_reader();}
00194 
00196 
00197     bool try_lock_read() {return internal_try_acquire_reader();}
00198 
00199 private:
00200     typedef intptr_t state_t;
00201     static const state_t WRITER = 1;
00202     static const state_t WRITER_PENDING = 2;
00203     static const state_t READERS = ~(WRITER | WRITER_PENDING);
00204     static const state_t ONE_READER = 4;
00205     static const state_t BUSY = WRITER | READERS;
00207 
00210     state_t state;
00211 
00212     void __TBB_EXPORTED_METHOD internal_construct();
00213 };
00214 
00215 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
00216 
00217 } // namespace tbb
00218 
00219 #endif /* __TBB_spin_rw_mutex_H */

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