Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*
0002     Copyright (c) 2021-2023 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__address_waiters_H
0018 #define __TBB_detail__address_waiters_H
0019 
0020 #include "_utils.h"
0021 
0022 namespace tbb {
0023 namespace detail {
0024 
0025 namespace r1 {
0026 TBB_EXPORT void __TBB_EXPORTED_FUNC wait_on_address(void* address, d1::delegate_base& wakeup_condition, std::uintptr_t context);
0027 TBB_EXPORT void __TBB_EXPORTED_FUNC notify_by_address(void* address, std::uintptr_t context);
0028 TBB_EXPORT void __TBB_EXPORTED_FUNC notify_by_address_one(void* address);
0029 TBB_EXPORT void __TBB_EXPORTED_FUNC notify_by_address_all(void* address);
0030 } // namespace r1
0031 
0032 namespace d1 {
0033 
0034 template <typename Predicate>
0035 void adaptive_wait_on_address(void* address, Predicate wakeup_condition, std::uintptr_t context) {
0036     if (!timed_spin_wait_until(wakeup_condition)) {
0037         d1::delegated_function<Predicate> pred(wakeup_condition);
0038         r1::wait_on_address(address, pred, context);
0039     }
0040 }
0041 
0042 template <typename T>
0043 class waitable_atomic {
0044 public:
0045     waitable_atomic() = default;
0046 
0047     explicit waitable_atomic(T value) : my_atomic(value) {}
0048 
0049     waitable_atomic(const waitable_atomic&) = delete;
0050     waitable_atomic& operator=(const waitable_atomic&) = delete;
0051 
0052     T load(std::memory_order order) const noexcept {
0053         return my_atomic.load(order);
0054     }
0055 
0056     T exchange(T desired) noexcept {
0057         return my_atomic.exchange(desired);
0058     }
0059 
0060     void wait(T old, std::uintptr_t context, std::memory_order order) {
0061         auto wakeup_condition = [&] { return my_atomic.load(order) != old; };
0062         if (!timed_spin_wait_until(wakeup_condition)) {
0063             // We need to use while here, because notify_all() will wake up all threads
0064             // But predicate for them might be false
0065             d1::delegated_function<decltype(wakeup_condition)> pred(wakeup_condition);
0066             do {
0067                 r1::wait_on_address(this, pred, context);
0068             } while (!wakeup_condition());
0069         }
0070     }
0071 
0072     void notify_one_relaxed() {
0073         r1::notify_by_address_one(this);
0074     }
0075 
0076     // TODO: consider adding following interfaces:
0077     // store(desired, memory_order)
0078     // notify_all_relaxed()
0079     // wait_until(T, std::uintptr_t, std::memory_order)
0080     // notify_relaxed(std::uintptr_t context)
0081 
0082 private:
0083     std::atomic<T> my_atomic{};
0084 };
0085 
0086 } // namespace d1
0087 } // namespace detail
0088 } // namespace tbb
0089 
0090 #endif // __TBB_detail__address_waiters_H