Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/oneapi/tbb/task_scheduler_observer.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_task_scheduler_observer_H
0018 #define __TBB_task_scheduler_observer_H
0019 
0020 #include "detail/_namespace_injection.h"
0021 #include "task_arena.h"
0022 #include <atomic>
0023 
0024 namespace tbb {
0025 namespace detail {
0026 
0027 namespace d1 {
0028 class task_scheduler_observer;
0029 }
0030 
0031 namespace r1 {
0032 class observer_proxy;
0033 class observer_list;
0034 
0035 //! Enable or disable observation
0036 /** For local observers the method can be used only when the current thread
0037 has the task scheduler initialized or is attached to an arena.
0038 Repeated calls with the same state are no-ops. **/
0039 TBB_EXPORT void __TBB_EXPORTED_FUNC observe(d1::task_scheduler_observer&, bool state = true);
0040 }
0041 
0042 namespace d1 {
0043 class task_scheduler_observer {
0044     friend class r1::observer_proxy;
0045     friend class r1::observer_list;
0046     friend void r1::observe(d1::task_scheduler_observer&, bool);
0047 
0048     //! Pointer to the proxy holding this observer.
0049     /** Observers are proxied by the scheduler to maintain persistent lists of them. **/
0050     std::atomic<r1::observer_proxy*> my_proxy{ nullptr };
0051 
0052     //! Counter preventing the observer from being destroyed while in use by the scheduler.
0053     /** Valid only when observation is on. **/
0054     std::atomic<intptr_t> my_busy_count{ 0 };
0055 
0056     //! Contains task_arena pointer
0057     task_arena* my_task_arena{ nullptr };
0058 public:
0059     //! Returns true if observation is enabled, false otherwise.
0060     bool is_observing() const { return my_proxy.load(std::memory_order_relaxed) != nullptr; }
0061 
0062     //! Entry notification
0063     /** Invoked from inside observe(true) call and whenever a worker enters the arena
0064         this observer is associated with. If a thread is already in the arena when
0065         the observer is activated, the entry notification is called before it
0066         executes the first stolen task. **/
0067     virtual void on_scheduler_entry( bool /*is_worker*/ ) {}
0068 
0069     //! Exit notification
0070     /** Invoked from inside observe(false) call and whenever a worker leaves the
0071         arena this observer is associated with. **/
0072     virtual void on_scheduler_exit( bool /*is_worker*/ ) {}
0073 
0074     //! Construct local or global observer in inactive state (observation disabled).
0075     /** For a local observer entry/exit notifications are invoked whenever a worker
0076         thread joins/leaves the arena of the observer's owner thread. If a thread is
0077         already in the arena when the observer is activated, the entry notification is
0078         called before it executes the first stolen task. **/
0079     explicit task_scheduler_observer() = default;
0080 
0081     //! Construct local observer for a given arena in inactive state (observation disabled).
0082     /** entry/exit notifications are invoked whenever a thread joins/leaves arena.
0083         If a thread is already in the arena when the observer is activated, the entry notification
0084         is called before it executes the first stolen task. **/
0085     explicit task_scheduler_observer(task_arena& a) : my_task_arena(&a) {}
0086 
0087     /** Destructor protects instance of the observer from concurrent notification.
0088        It is recommended to disable observation before destructor of a derived class starts,
0089        otherwise it can lead to concurrent notification callback on partly destroyed object **/
0090     virtual ~task_scheduler_observer() {
0091         if (my_proxy.load(std::memory_order_acquire)) {
0092             observe(false);
0093         }
0094     }
0095 
0096     //! Enable or disable observation
0097     /** Warning: concurrent invocations of this method are not safe.
0098         Repeated calls with the same state are no-ops. **/
0099     void observe(bool state = true) {
0100         if( state && !my_proxy.load(std::memory_order_relaxed) ) {
0101             __TBB_ASSERT( my_busy_count.load(std::memory_order_relaxed) == 0, "Inconsistent state of task_scheduler_observer instance");
0102         }
0103         r1::observe(*this, state);
0104     }
0105 };
0106 
0107 } // namespace d1
0108 } // namespace detail
0109 
0110 inline namespace v1 {
0111     using detail::d1::task_scheduler_observer;
0112 }
0113 } // namespace tbb
0114 
0115 
0116 #endif /* __TBB_task_scheduler_observer_H */