128 Bucket::release_assign_last_node_next( 129 typename ConcurrentHashTable<CONFIG, F>::Node* node) 130 { 131 assert(is_locked(), "Must be locked."); 132 Node* const volatile * ret = first_ptr(); 133 while (clear_state(*ret) != NULL) { 134 ret = clear_state(*ret)->next_ptr(); 135 } 136 release_assign_node_ptr(ret, node); 137 } 138 139 template <typename CONFIG, MEMFLAGS F> 140 inline bool ConcurrentHashTable<CONFIG, F>:: 141 Bucket::cas_first(typename ConcurrentHashTable<CONFIG, F>::Node* node, 142 typename ConcurrentHashTable<CONFIG, F>::Node* expect 143 ) 144 { 145 if (is_locked()) { 146 return false; 147 } 148 if (Atomic::cmpxchg(node, &_first, expect) == expect) { 149 return true; 150 } 151 return false; 152 } 153 154 template <typename CONFIG, MEMFLAGS F> 155 inline bool ConcurrentHashTable<CONFIG, F>:: 156 Bucket::trylock() 157 { 158 if (is_locked()) { 159 return false; 160 } 161 // We will expect a clean first pointer. 162 Node* tmp = first(); 163 if (Atomic::cmpxchg(set_state(tmp, STATE_LOCK_BIT), &_first, tmp) == tmp) { 164 return true; 165 } 166 return false; 167 } 168 169 template <typename CONFIG, MEMFLAGS F> 170 inline void ConcurrentHashTable<CONFIG, F>:: 171 Bucket::unlock() 172 { 173 assert(is_locked(), "Must be locked."); 174 assert(!have_redirect(), 175 "Unlocking a bucket after it has reached terminal state."); 176 Atomic::release_store(&_first, clear_state(first())); 177 } 178 179 template <typename CONFIG, MEMFLAGS F> 180 inline void ConcurrentHashTable<CONFIG, F>:: 181 Bucket::redirect() 182 { 183 assert(is_locked(), "Must be locked."); | 128 Bucket::release_assign_last_node_next( 129 typename ConcurrentHashTable<CONFIG, F>::Node* node) 130 { 131 assert(is_locked(), "Must be locked."); 132 Node* const volatile * ret = first_ptr(); 133 while (clear_state(*ret) != NULL) { 134 ret = clear_state(*ret)->next_ptr(); 135 } 136 release_assign_node_ptr(ret, node); 137 } 138 139 template <typename CONFIG, MEMFLAGS F> 140 inline bool ConcurrentHashTable<CONFIG, F>:: 141 Bucket::cas_first(typename ConcurrentHashTable<CONFIG, F>::Node* node, 142 typename ConcurrentHashTable<CONFIG, F>::Node* expect 143 ) 144 { 145 if (is_locked()) { 146 return false; 147 } 148 if (Atomic::cmpxchg(&_first, expect, node) == expect) { 149 return true; 150 } 151 return false; 152 } 153 154 template <typename CONFIG, MEMFLAGS F> 155 inline bool ConcurrentHashTable<CONFIG, F>:: 156 Bucket::trylock() 157 { 158 if (is_locked()) { 159 return false; 160 } 161 // We will expect a clean first pointer. 162 Node* tmp = first(); 163 if (Atomic::cmpxchg(&_first, tmp, set_state(tmp, STATE_LOCK_BIT)) == tmp) { 164 return true; 165 } 166 return false; 167 } 168 169 template <typename CONFIG, MEMFLAGS F> 170 inline void ConcurrentHashTable<CONFIG, F>:: 171 Bucket::unlock() 172 { 173 assert(is_locked(), "Must be locked."); 174 assert(!have_redirect(), 175 "Unlocking a bucket after it has reached terminal state."); 176 Atomic::release_store(&_first, clear_state(first())); 177 } 178 179 template <typename CONFIG, MEMFLAGS F> 180 inline void ConcurrentHashTable<CONFIG, F>:: 181 Bucket::redirect() 182 { 183 assert(is_locked(), "Must be locked."); |