00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_queuing_rw_mutex_H
00022 #define __TBB_queuing_rw_mutex_H
00023
00024 #include <cstring>
00025 #include "atomic.h"
00026
00027 namespace tbb {
00028
00030
00033 class queuing_rw_mutex {
00034 public:
00036 queuing_rw_mutex() {
00037 q_tail = NULL;
00038 };
00039
00041 ~queuing_rw_mutex() {
00042 #if TBB_DO_ASSERT
00043 __TBB_ASSERT( !q_tail, "destruction of an acquired mutex");
00044 #endif
00045 };
00046
00047 class scoped_lock;
00048 friend class scoped_lock;
00049
00051
00053 class scoped_lock : private internal::no_copy {
00055 enum state_t {
00056 STATE_NONE = 0,
00057 STATE_WRITER = 1,
00058 STATE_READER = 1<<1,
00059 STATE_READER_UNBLOCKNEXT = 1<<2,
00060 STATE_COMBINED_WAITINGREADER = STATE_READER | STATE_READER_UNBLOCKNEXT,
00061 STATE_ACTIVEREADER = 1<<3,
00062 STATE_COMBINED_READER = STATE_COMBINED_WAITINGREADER | STATE_ACTIVEREADER,
00063 STATE_UPGRADE_REQUESTED = 1<<4,
00064 STATE_UPGRADE_WAITING = 1<<5,
00065 STATE_UPGRADE_LOSER = 1<<6,
00066 STATE_COMBINED_UPGRADING = STATE_UPGRADE_WAITING | STATE_UPGRADE_LOSER
00067 #if TBB_DO_ASSERT
00068 ,STATE_INVALID
00069 #endif
00070 };
00071
00073 void initialize() {
00074 mutex = NULL;
00075 #if TBB_DO_ASSERT
00076 state = STATE_INVALID;
00077 internal::poison_pointer(next);
00078 internal::poison_pointer(prev);
00079 #endif
00080 }
00081 public:
00083
00084 scoped_lock() {initialize();}
00085
00087
00088 scoped_lock( queuing_rw_mutex& m, bool write=true ) {
00089 initialize();
00090 acquire(m,write);
00091 }
00092
00094 ~scoped_lock() {
00095 if( mutex ) release();
00096 }
00097
00099 void acquire( queuing_rw_mutex& m, bool write=true );
00100
00102 bool try_acquire( queuing_rw_mutex& m, bool write=true );
00103
00105 void release();
00106
00108
00109 bool upgrade_to_writer();
00110
00112 bool downgrade_to_reader();
00113
00114 private:
00116 queuing_rw_mutex* mutex;
00117
00119 scoped_lock * prev, * next;
00120
00122 atomic<unsigned char> state;
00123
00125
00126 unsigned char going;
00127
00129 unsigned char internal_lock;
00130
00132 void acquire_internal_lock();
00133
00135
00136 bool try_acquire_internal_lock();
00137
00139 void release_internal_lock();
00140
00142 void wait_for_release_of_internal_lock();
00143
00145 void unblock_or_wait_on_internal_lock( uintptr_t );
00146 };
00147
00148
00149 static const bool is_rw_mutex = true;
00150 static const bool is_recursive_mutex = false;
00151 static const bool is_fair_mutex = true;
00152
00153 private:
00155 atomic<scoped_lock*> q_tail;
00156
00157 };
00158
00159 }
00160
00161 #endif