Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/oneapi/tbb/global_control.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     Copyright (c) 2005-2021 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_global_control_H
0018 #define __TBB_global_control_H
0019 
0020 #include "detail/_config.h"
0021 
0022 #include "detail/_assert.h"
0023 #include "detail/_attach.h"
0024 #include "detail/_exception.h"
0025 #include "detail/_namespace_injection.h"
0026 #include "detail/_template_helpers.h"
0027 
0028 #include <cstddef>
0029 #include <new> // std::nothrow_t
0030 
0031 namespace tbb {
0032 namespace detail {
0033 
0034 namespace d1 {
0035 class global_control;
0036 class task_scheduler_handle;
0037 }
0038 
0039 namespace r1 {
0040 TBB_EXPORT void __TBB_EXPORTED_FUNC create(d1::global_control&);
0041 TBB_EXPORT void __TBB_EXPORTED_FUNC destroy(d1::global_control&);
0042 TBB_EXPORT std::size_t __TBB_EXPORTED_FUNC global_control_active_value(int);
0043 struct global_control_impl;
0044 struct control_storage_comparator;
0045 void release_impl(d1::task_scheduler_handle& handle);
0046 bool finalize_impl(d1::task_scheduler_handle& handle);
0047 TBB_EXPORT void __TBB_EXPORTED_FUNC get(d1::task_scheduler_handle&);
0048 TBB_EXPORT bool __TBB_EXPORTED_FUNC finalize(d1::task_scheduler_handle&, std::intptr_t mode);
0049 }
0050 
0051 namespace d1 {
0052 
0053 class global_control {
0054 public:
0055     enum parameter {
0056         max_allowed_parallelism,
0057         thread_stack_size,
0058         terminate_on_exception,
0059         scheduler_handle, // not a public parameter
0060         parameter_max // insert new parameters above this point
0061     };
0062 
0063     global_control(parameter p, std::size_t value) :
0064         my_value(value), my_reserved(), my_param(p) {
0065         suppress_unused_warning(my_reserved);
0066         __TBB_ASSERT(my_param < parameter_max, "Invalid parameter");
0067 #if __TBB_WIN8UI_SUPPORT && (_WIN32_WINNT < 0x0A00)
0068         // For Windows 8 Store* apps it's impossible to set stack size
0069         if (p==thread_stack_size)
0070             return;
0071 #elif __TBB_x86_64 && (_WIN32 || _WIN64)
0072         if (p==thread_stack_size)
0073             __TBB_ASSERT_RELEASE((unsigned)value == value, "Stack size is limited to unsigned int range");
0074 #endif
0075         if (my_param==max_allowed_parallelism)
0076             __TBB_ASSERT_RELEASE(my_value>0, "max_allowed_parallelism cannot be 0.");
0077         r1::create(*this);
0078     }
0079 
0080     ~global_control() {
0081         __TBB_ASSERT(my_param < parameter_max, "Invalid parameter");
0082 #if __TBB_WIN8UI_SUPPORT && (_WIN32_WINNT < 0x0A00)
0083         // For Windows 8 Store* apps it's impossible to set stack size
0084         if (my_param==thread_stack_size)
0085             return;
0086 #endif
0087         r1::destroy(*this);
0088     }
0089 
0090     static std::size_t active_value(parameter p) {
0091         __TBB_ASSERT(p < parameter_max, "Invalid parameter");
0092         return r1::global_control_active_value((int)p);
0093     }
0094 
0095 private:
0096     std::size_t my_value;
0097     std::intptr_t my_reserved; // TODO: substitution of global_control* not to break backward compatibility
0098     parameter my_param;
0099 
0100     friend struct r1::global_control_impl;
0101     friend struct r1::control_storage_comparator;
0102 };
0103 
0104 //! Finalization options.
0105 //! Outside of the class to avoid extensive friendship.
0106 static constexpr std::intptr_t release_nothrowing = 0;
0107 static constexpr std::intptr_t finalize_nothrowing = 1;
0108 static constexpr std::intptr_t finalize_throwing = 2;
0109 
0110 //! User side wrapper for a task scheduler lifetime control object
0111 class task_scheduler_handle {
0112 public:
0113     //! Creates an empty task_scheduler_handle
0114     task_scheduler_handle() = default;
0115 
0116     //! Creates an attached instance of task_scheduler_handle
0117     task_scheduler_handle(attach) {
0118         r1::get(*this);
0119     }
0120 
0121     //! Release a reference if any
0122     ~task_scheduler_handle() {
0123         release();
0124     }
0125 
0126     //! No copy
0127     task_scheduler_handle(const task_scheduler_handle& other) = delete;
0128     task_scheduler_handle& operator=(const task_scheduler_handle& other) = delete;
0129 
0130     //! Move only
0131     task_scheduler_handle(task_scheduler_handle&& other) noexcept {
0132         std::swap(m_ctl, other.m_ctl);
0133     }
0134     task_scheduler_handle& operator=(task_scheduler_handle&& other) noexcept {
0135         std::swap(m_ctl, other.m_ctl);
0136         return *this;
0137     };
0138 
0139     //! Checks if the task_scheduler_handle is empty
0140     explicit operator bool() const noexcept {
0141         return m_ctl != nullptr;
0142     }
0143 
0144     //! Release the reference and deactivate handle
0145     void release() {
0146         if (m_ctl != nullptr) {
0147             r1::finalize(*this, release_nothrowing);
0148             m_ctl = nullptr;
0149         }
0150     }
0151 
0152 private:
0153     friend void r1::release_impl(task_scheduler_handle& handle);
0154     friend bool r1::finalize_impl(task_scheduler_handle& handle);
0155     friend void __TBB_EXPORTED_FUNC r1::get(task_scheduler_handle&);
0156 
0157     friend void finalize(task_scheduler_handle&);
0158     friend bool finalize(task_scheduler_handle&, const std::nothrow_t&) noexcept;
0159 
0160     global_control* m_ctl{nullptr};
0161 };
0162 
0163 #if TBB_USE_EXCEPTIONS
0164 //! Waits for worker threads termination. Throws exception on error.
0165 inline void finalize(task_scheduler_handle& handle) {
0166     try_call([&] {
0167         if (handle.m_ctl != nullptr) {
0168             bool finalized = r1::finalize(handle, finalize_throwing);
0169             __TBB_ASSERT_EX(finalized, "r1::finalize did not respect finalize_throwing ?");
0170             
0171         }
0172     }).on_completion([&] {
0173         __TBB_ASSERT(!handle, "The handle should be empty after finalize");
0174     });
0175 }
0176 #endif
0177 //! Waits for worker threads termination. Returns false on error.
0178 inline bool finalize(task_scheduler_handle& handle, const std::nothrow_t&) noexcept {
0179     bool finalized = true;
0180     if (handle.m_ctl != nullptr) {
0181         finalized = r1::finalize(handle, finalize_nothrowing);
0182     }
0183     __TBB_ASSERT(!handle, "The handle should be empty after finalize");
0184     return finalized;
0185 }
0186 
0187 } // namespace d1
0188 } // namespace detail
0189 
0190 inline namespace v1 {
0191 using detail::d1::global_control;
0192 using detail::d1::attach;
0193 using detail::d1::finalize;
0194 using detail::d1::task_scheduler_handle;
0195 using detail::r1::unsafe_wait;
0196 } // namespace v1
0197 
0198 } // namespace tbb
0199 
0200 #endif // __TBB_global_control_H