Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-30 08:46:19

0001 /*
0002     Copyright (c) 2005-2022 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 #ifndef __TBB_detail_scoped_lock_H
0018 #define __TBB_detail_scoped_lock_H
0019 
0020 namespace tbb {
0021 namespace detail {
0022 namespace d1 {
0023 
0024 // unique_scoped_lock supposes that Mutex operations never throw
0025 template <typename Mutex>
0026 class unique_scoped_lock {
0027     //! Points to currently held Mutex, or nullptr if no lock is held.
0028     Mutex* m_mutex{};
0029 
0030 public:
0031     //! Construct without acquiring a Mutex.
0032     constexpr unique_scoped_lock() noexcept : m_mutex(nullptr) {}
0033 
0034     //! Construct and acquire lock on a Mutex.
0035     unique_scoped_lock(Mutex& m) {
0036         acquire(m);
0037     }
0038 
0039     //! No Copy
0040     unique_scoped_lock(const unique_scoped_lock&) = delete;
0041     unique_scoped_lock& operator=(const unique_scoped_lock&) = delete;
0042 
0043     //! Acquire lock.
0044     void acquire(Mutex& m) {
0045         __TBB_ASSERT(m_mutex == nullptr, "The mutex is already acquired");
0046         m_mutex = &m;
0047         m.lock();
0048     }
0049 
0050     //! Try acquiring lock (non-blocking)
0051     /** Return true if lock acquired; false otherwise. */
0052     bool try_acquire(Mutex& m) {
0053         __TBB_ASSERT(m_mutex == nullptr, "The mutex is already acquired");
0054         bool succeed = m.try_lock();
0055         if (succeed) {
0056             m_mutex = &m;
0057         }
0058         return succeed;
0059     }
0060 
0061     //! Release lock
0062     void release() {
0063         __TBB_ASSERT(m_mutex, "release on Mutex::unique_scoped_lock that is not holding a lock");
0064         m_mutex->unlock();
0065         m_mutex = nullptr;
0066     }
0067 
0068     //! Destroy lock. If holding a lock, releases the lock first.
0069     ~unique_scoped_lock() {
0070         if (m_mutex) {
0071             release();
0072         }
0073     }
0074 };
0075 
0076 // rw_scoped_lock supposes that Mutex operations never throw
0077 template <typename Mutex>
0078 class rw_scoped_lock {
0079 public:
0080     //! Construct lock that has not acquired a mutex.
0081     /** Equivalent to zero-initialization of *this. */
0082     constexpr rw_scoped_lock() noexcept {}
0083 
0084     //! Acquire lock on given mutex.
0085     rw_scoped_lock(Mutex& m, bool write = true) {
0086         acquire(m, write);
0087     }
0088 
0089     //! Release lock (if lock is held).
0090     ~rw_scoped_lock() {
0091         if (m_mutex) {
0092             release();
0093         }
0094     }
0095 
0096     //! No Copy
0097     rw_scoped_lock(const rw_scoped_lock&) = delete;
0098     rw_scoped_lock& operator=(const rw_scoped_lock&) = delete;
0099 
0100     //! Acquire lock on given mutex.
0101     void acquire(Mutex& m, bool write = true) {
0102         __TBB_ASSERT(m_mutex == nullptr, "The mutex is already acquired");
0103         m_is_writer = write;
0104         m_mutex = &m;
0105         if (write) {
0106             m_mutex->lock();
0107         } else {
0108             m_mutex->lock_shared();
0109         }
0110     }
0111 
0112     //! Try acquire lock on given mutex.
0113     bool try_acquire(Mutex& m, bool write = true) {
0114         bool succeed = write ? m.try_lock() : m.try_lock_shared();
0115         if (succeed) {
0116             m_mutex = &m;
0117             m_is_writer = write;
0118         }
0119         return succeed;
0120     }
0121 
0122     //! Release lock.
0123     void release() {
0124         __TBB_ASSERT(m_mutex != nullptr, "The mutex is not acquired");
0125         Mutex* m = m_mutex;
0126         m_mutex = nullptr;
0127 
0128         if (m_is_writer) {
0129             m->unlock();
0130         } else {
0131             m->unlock_shared();
0132         }
0133     }
0134 
0135     //! Upgrade reader to become a writer.
0136     /** Returns whether the upgrade happened without releasing and re-acquiring the lock */
0137     bool upgrade_to_writer() {
0138         __TBB_ASSERT(m_mutex != nullptr, "The mutex is not acquired");
0139         if (m_is_writer) {
0140             return true; // Already a writer
0141         }
0142         m_is_writer = true;
0143         return m_mutex->upgrade();
0144     }
0145 
0146     //! Downgrade writer to become a reader.
0147     bool downgrade_to_reader() {
0148         __TBB_ASSERT(m_mutex != nullptr, "The mutex is not acquired");
0149         if (m_is_writer) {
0150             m_mutex->downgrade();
0151             m_is_writer = false;
0152         }
0153         return true;
0154     }
0155 
0156     bool is_writer() const {
0157         __TBB_ASSERT(m_mutex != nullptr, "The mutex is not acquired");
0158         return m_is_writer;
0159     }
0160 
0161 protected:
0162     //! The pointer to the current mutex that is held, or nullptr if no mutex is held.
0163     Mutex* m_mutex {nullptr};
0164 
0165     //! If mutex != nullptr, then is_writer is true if holding a writer lock, false if holding a reader lock.
0166     /** Not defined if not holding a lock. */
0167     bool m_is_writer {false};
0168 };
0169 
0170 } // namespace d1
0171 } // namespace detail
0172 } // namespace tbb
0173 
0174 #endif // __TBB_detail_scoped_lock_H