|
||||
File indexing completed on 2025-01-18 10:12:59
0001 /* 0002 Copyright (c) 2005-2020 Intel Corporation 0003 0004 Licensed under the Apache License, Version 2.0 (the "License"); 0005 you may not use this file except in compliance with the License. 0006 You may obtain a copy of the License at 0007 0008 http://www.apache.org/licenses/LICENSE-2.0 0009 0010 Unless required by applicable law or agreed to in writing, software 0011 distributed under the License is distributed on an "AS IS" BASIS, 0012 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 See the License for the specific language governing permissions and 0014 limitations under the License. 0015 */ 0016 0017 #include "internal/_deprecated_header_message_guard.h" 0018 0019 #if !defined(__TBB_show_deprecation_message_reader_writer_lock_H) && defined(__TBB_show_deprecated_header_message) 0020 #define __TBB_show_deprecation_message_reader_writer_lock_H 0021 #pragma message("TBB Warning: tbb/reader_writer_lock.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.") 0022 #endif 0023 0024 #if defined(__TBB_show_deprecated_header_message) 0025 #undef __TBB_show_deprecated_header_message 0026 #endif 0027 0028 #ifndef __TBB_reader_writer_lock_H 0029 #define __TBB_reader_writer_lock_H 0030 0031 #define __TBB_reader_writer_lock_H_include_area 0032 #include "internal/_warning_suppress_enable_notice.h" 0033 0034 #include "tbb_thread.h" 0035 #include "tbb_allocator.h" 0036 #include "atomic.h" 0037 0038 namespace tbb { 0039 namespace interface5 { 0040 //! Writer-preference reader-writer lock with local-only spinning on readers. 0041 /** Loosely adapted from Mellor-Crummey and Scott pseudocode at 0042 http://www.cs.rochester.edu/research/synchronization/pseudocode/rw.html#s_wp 0043 @ingroup synchronization */ 0044 class __TBB_DEPRECATED_IN_VERBOSE_MODE_MSG("tbb::reader_writer_lock is deprecated, use std::shared_mutex") 0045 reader_writer_lock : tbb::internal::no_copy { 0046 public: 0047 friend class scoped_lock; 0048 friend class scoped_lock_read; 0049 //! Status type for nodes associated with lock instances 0050 /** waiting_nonblocking: the wait state for nonblocking lock 0051 instances; for writes, these transition straight to active 0052 states; for reads, these are unused. 0053 0054 waiting: the start and spin state for all lock instances; these will 0055 transition to active state when appropriate. Non-blocking write locks 0056 transition from this state to waiting_nonblocking immediately. 0057 0058 active: the active state means that the lock instance holds 0059 the lock; it will transition to invalid state during node deletion 0060 0061 invalid: the end state for all nodes; this is set in the 0062 destructor so if we encounter this state, we are looking at 0063 memory that has already been freed 0064 0065 The state diagrams below describe the status transitions. 0066 Single arrows indicate that the thread that owns the node is 0067 responsible for the transition; double arrows indicate that 0068 any thread could make the transition. 0069 0070 State diagram for scoped_lock status: 0071 0072 waiting ----------> waiting_nonblocking 0073 | _____________/ | 0074 V V V 0075 active -----------------> invalid 0076 0077 State diagram for scoped_lock_read status: 0078 0079 waiting 0080 | 0081 V 0082 active ----------------->invalid 0083 0084 */ 0085 enum status_t { waiting_nonblocking, waiting, active, invalid }; 0086 0087 //! Constructs a new reader_writer_lock 0088 reader_writer_lock() { 0089 internal_construct(); 0090 } 0091 0092 //! Destructs a reader_writer_lock object 0093 ~reader_writer_lock() { 0094 internal_destroy(); 0095 } 0096 0097 //! The scoped lock pattern for write locks 0098 /** Scoped locks help avoid the common problem of forgetting to release the lock. 0099 This type also serves as the node for queuing locks. */ 0100 class scoped_lock : tbb::internal::no_copy { 0101 public: 0102 friend class reader_writer_lock; 0103 0104 //! Construct with blocking attempt to acquire write lock on the passed-in lock 0105 scoped_lock(reader_writer_lock& lock) { 0106 internal_construct(lock); 0107 } 0108 0109 //! Destructor, releases the write lock 0110 ~scoped_lock() { 0111 internal_destroy(); 0112 } 0113 0114 void* operator new(size_t s) { 0115 return tbb::internal::allocate_via_handler_v3(s); 0116 } 0117 void operator delete(void* p) { 0118 tbb::internal::deallocate_via_handler_v3(p); 0119 } 0120 0121 private: 0122 //! The pointer to the mutex to lock 0123 reader_writer_lock *mutex; 0124 //! The next queued competitor for the mutex 0125 scoped_lock* next; 0126 //! Status flag of the thread associated with this node 0127 atomic<status_t> status; 0128 0129 //! Construct scoped_lock that is not holding lock 0130 scoped_lock(); 0131 0132 void __TBB_EXPORTED_METHOD internal_construct(reader_writer_lock&); 0133 void __TBB_EXPORTED_METHOD internal_destroy(); 0134 }; 0135 0136 //! The scoped lock pattern for read locks 0137 class scoped_lock_read : tbb::internal::no_copy { 0138 public: 0139 friend class reader_writer_lock; 0140 0141 //! Construct with blocking attempt to acquire read lock on the passed-in lock 0142 scoped_lock_read(reader_writer_lock& lock) { 0143 internal_construct(lock); 0144 } 0145 0146 //! Destructor, releases the read lock 0147 ~scoped_lock_read() { 0148 internal_destroy(); 0149 } 0150 0151 void* operator new(size_t s) { 0152 return tbb::internal::allocate_via_handler_v3(s); 0153 } 0154 void operator delete(void* p) { 0155 tbb::internal::deallocate_via_handler_v3(p); 0156 } 0157 0158 private: 0159 //! The pointer to the mutex to lock 0160 reader_writer_lock *mutex; 0161 //! The next queued competitor for the mutex 0162 scoped_lock_read *next; 0163 //! Status flag of the thread associated with this node 0164 atomic<status_t> status; 0165 0166 //! Construct scoped_lock_read that is not holding lock 0167 scoped_lock_read(); 0168 0169 void __TBB_EXPORTED_METHOD internal_construct(reader_writer_lock&); 0170 void __TBB_EXPORTED_METHOD internal_destroy(); 0171 }; 0172 0173 //! Acquires the reader_writer_lock for write. 0174 /** If the lock is currently held in write mode by another 0175 context, the writer will block by spinning on a local 0176 variable. Exceptions thrown: improper_lock The context tries 0177 to acquire a reader_writer_lock that it already has write 0178 ownership of.*/ 0179 void __TBB_EXPORTED_METHOD lock(); 0180 0181 //! Tries to acquire the reader_writer_lock for write. 0182 /** This function does not block. Return Value: True or false, 0183 depending on whether the lock is acquired or not. If the lock 0184 is already held by this acquiring context, try_lock() returns 0185 false. */ 0186 bool __TBB_EXPORTED_METHOD try_lock(); 0187 0188 //! Acquires the reader_writer_lock for read. 0189 /** If the lock is currently held by a writer, this reader will 0190 block and wait until the writers are done. Exceptions thrown: 0191 improper_lock The context tries to acquire a 0192 reader_writer_lock that it already has write ownership of. */ 0193 void __TBB_EXPORTED_METHOD lock_read(); 0194 0195 //! Tries to acquire the reader_writer_lock for read. 0196 /** This function does not block. Return Value: True or false, 0197 depending on whether the lock is acquired or not. */ 0198 bool __TBB_EXPORTED_METHOD try_lock_read(); 0199 0200 //! Releases the reader_writer_lock 0201 void __TBB_EXPORTED_METHOD unlock(); 0202 0203 private: 0204 void __TBB_EXPORTED_METHOD internal_construct(); 0205 void __TBB_EXPORTED_METHOD internal_destroy(); 0206 0207 //! Attempts to acquire write lock 0208 /** If unavailable, spins in blocking case, returns false in non-blocking case. */ 0209 bool start_write(scoped_lock *); 0210 //! Sets writer_head to w and attempts to unblock 0211 void set_next_writer(scoped_lock *w); 0212 //! Relinquishes write lock to next waiting writer or group of readers 0213 void end_write(scoped_lock *); 0214 //! Checks if current thread holds write lock 0215 bool is_current_writer(); 0216 0217 //! Attempts to acquire read lock 0218 /** If unavailable, spins in blocking case, returns false in non-blocking case. */ 0219 void start_read(scoped_lock_read *); 0220 //! Unblocks pending readers 0221 void unblock_readers(); 0222 //! Relinquishes read lock by decrementing counter; last reader wakes pending writer 0223 void end_read(); 0224 0225 //! The list of pending readers 0226 atomic<scoped_lock_read*> reader_head; 0227 //! The list of pending writers 0228 atomic<scoped_lock*> writer_head; 0229 //! The last node in the list of pending writers 0230 atomic<scoped_lock*> writer_tail; 0231 //! Writer that owns the mutex; tbb_thread::id() otherwise. 0232 tbb_thread::id my_current_writer; 0233 //! Status of mutex 0234 atomic<uintptr_t> rdr_count_and_flags; // used with __TBB_AtomicOR, which assumes uintptr_t 0235 }; 0236 0237 } // namespace interface5 0238 0239 using interface5::reader_writer_lock; 0240 0241 } // namespace tbb 0242 0243 #include "internal/_warning_suppress_disable_notice.h" 0244 #undef __TBB_reader_writer_lock_H_include_area 0245 0246 #endif /* __TBB_reader_writer_lock_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |