- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

# spin_rw_mutex.h

    00001 /*
    00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
    00003
    00004     This file is part of Threading Building Blocks.
    00005
    00006     Threading Building Blocks is free software; you can redistribute it
    00007     and/or modify it under the terms of the GNU General Public License
    00008     version 2 as published by the Free Software Foundation.
    00009
    00010     Threading Building Blocks is distributed in the hope that it will be
    00011     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    00012     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013     GNU General Public License for more details.
    00014
    00015     You should have received a copy of the GNU General Public License
    00016     along with Threading Building Blocks; if not, write to the Free Software
    00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    00018
    00019     As a special exception, you may use this file as part of a free software
    00020     library without restriction.  Specifically, if other files instantiate
    00021     templates or use macros or inline functions from this file, or you compile
    00022     this file and link it with other files to produce an executable, this
    00023     file does not by itself cause the resulting executable to be covered by
    00024     the GNU General Public License.  This exception does not however
    00025     invalidate any other reasons why the executable file might be covered by
    00026     the GNU General Public License.
    00027 */
    00028
    00029 #ifndef __TBB_spin_rw_mutex_H
    00030 #define __TBB_spin_rw_mutex_H
    00031
    00032 #include "tbb_stddef.h"
    00033 #include "tbb_machine.h"
    00034 #include "tbb_profiling.h"
    00035
    00036 namespace tbb {
    00037
    00038 class spin_rw_mutex_v3;
    00039 typedef spin_rw_mutex_v3 spin_rw_mutex;
    00040
    00042
    00043 class spin_rw_mutex_v3 {
    00045
    00047     bool __TBB_EXPORTED_METHOD internal_acquire_writer();
    00048
    00050
    00051     void __TBB_EXPORTED_METHOD internal_release_writer();
    00052
    00054     void __TBB_EXPORTED_METHOD internal_acquire_reader();
    00055
    00057     bool __TBB_EXPORTED_METHOD internal_upgrade();
    00058
    00060
    00061     void __TBB_EXPORTED_METHOD internal_downgrade();
    00062
    00064     void __TBB_EXPORTED_METHOD internal_release_reader();
    00065
    00067     bool __TBB_EXPORTED_METHOD internal_try_acquire_writer();
    00068
    00070     bool __TBB_EXPORTED_METHOD internal_try_acquire_reader();
    00071
    00073 public:
    00075     spin_rw_mutex_v3() : state(0) {
    00076 #if TBB_USE_THREADING_TOOLS
    00077         internal_construct();
    00078 #endif
    00079     }
    00080
    00081 #if TBB_USE_ASSERT
    00083     ~spin_rw_mutex_v3() {
    00084         __TBB_ASSERT( !state, "destruction of an acquired mutex");
    00085     };
    00086 #endif /* TBB_USE_ASSERT */
    00087
    00089
    00091     class scoped_lock : internal::no_copy {
    00092     public:
    00094
    00095         scoped_lock() : mutex(NULL), is_writer(false) {}
    00096
    00098         scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
    00099             acquire(m, write);
    00100         }
    00101
    00103         ~scoped_lock() {
    00104             if( mutex ) release();
    00105         }
    00106
    00108         void acquire( spin_rw_mutex& m, bool write = true ) {
    00109             __TBB_ASSERT( !mutex, "holding mutex already" );
    00110             is_writer = write;
    00111             mutex = &m;
    00112             if( write ) mutex->internal_acquire_writer();
    00113             else        mutex->internal_acquire_reader();
    00114         }
    00115
    00117
    00118         bool upgrade_to_writer() {
    00119             __TBB_ASSERT( mutex, "lock is not acquired" );
    00120             __TBB_ASSERT( !is_writer, "not a reader" );
    00121             is_writer = true;
    00122             return mutex->internal_upgrade();
    00123         }
    00124
    00126         void release() {
    00127             __TBB_ASSERT( mutex, "lock is not acquired" );
    00128             spin_rw_mutex *m = mutex;
    00129             mutex = NULL;
    00130 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
    00131             if( is_writer ) m->internal_release_writer();
    00132             else            m->internal_release_reader();
    00133 #else
    00134             if( is_writer ) __TBB_AtomicAND( &m->state, READERS );
    00135             else            __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
    00136 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
    00137         }
    00138
    00140         bool downgrade_to_reader() {
    00141             __TBB_ASSERT( mutex, "lock is not acquired" );
    00142             __TBB_ASSERT( is_writer, "not a writer" );
    00143 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
    00144             mutex->internal_downgrade();
    00145 #else
    00146             __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
    00147 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
    00148             is_writer = false;
    00149             return true;
    00150         }
    00151
    00153         bool try_acquire( spin_rw_mutex& m, bool write = true ) {
    00154             __TBB_ASSERT( !mutex, "holding mutex already" );
    00155             bool result;
    00156             is_writer = write;
    00157             result = write? m.internal_try_acquire_writer()
    00158                           : m.internal_try_acquire_reader();
    00159             if( result )
    00160                 mutex = &m;
    00161             return result;
    00162         }
    00163
    00164     protected:
    00166         spin_rw_mutex* mutex;
    00167
    00169
    00170         bool is_writer;
    00171     };
    00172
    00173     // Mutex traits
    00174     static const bool is_rw_mutex = true;
    00175     static const bool is_recursive_mutex = false;
    00176     static const bool is_fair_mutex = false;
    00177
    00178     // ISO C++0x compatibility methods
    00179
    00181     void lock() {internal_acquire_writer();}
    00182
    00184
    00185     bool try_lock() {return internal_try_acquire_writer();}
    00186
    00188     void unlock() {
    00189 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
    00190         if( state&WRITER ) internal_release_writer();
    00191         else               internal_release_reader();
    00192 #else
    00193         if( state&WRITER ) __TBB_AtomicAND( &state, READERS );
    00194         else               __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
    00195 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
    00196     }
    00197
    00198     // Methods for reader locks that resemble ISO C++0x compatibility methods.
    00199
    00201     void lock_read() {internal_acquire_reader();}
    00202
    00204
    00205     bool try_lock_read() {return internal_try_acquire_reader();}
    00206
    00207 private:
    00208     typedef intptr_t state_t;
    00209     static const state_t WRITER = 1;
    00210     static const state_t WRITER_PENDING = 2;
    00211     static const state_t READERS = ~(WRITER | WRITER_PENDING);
    00212     static const state_t ONE_READER = 4;
    00213     static const state_t BUSY = WRITER | READERS;
    00215
    00218     state_t state;
    00219
    00220     void __TBB_EXPORTED_METHOD internal_construct();
    00221 };
    00222
    00223 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
    00224
    00225 } // namespace tbb
    00226
    00227 #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.