Back to home page

EIC code displayed by LXR

 
 

    


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 */