Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:13:00

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 #ifndef __TBB_task_scheduler_observer_H
0018 #define __TBB_task_scheduler_observer_H
0019 
0020 #define __TBB_task_scheduler_observer_H_include_area
0021 #include "internal/_warning_suppress_enable_notice.h"
0022 
0023 #include "atomic.h"
0024 #if __TBB_ARENA_OBSERVER
0025 #include "task_arena.h"
0026 #endif
0027 
0028 #if __TBB_SCHEDULER_OBSERVER
0029 
0030 namespace tbb {
0031 namespace interface6 {
0032 class task_scheduler_observer;
0033 }
0034 namespace internal {
0035 
0036 class observer_proxy;
0037 class observer_list;
0038 
0039 class task_scheduler_observer_v3 {
0040     friend class observer_proxy;
0041     friend class observer_list;
0042     friend class interface6::task_scheduler_observer;
0043 
0044     //! Pointer to the proxy holding this observer.
0045     /** Observers are proxied by the scheduler to maintain persistent lists of them. **/
0046     observer_proxy* my_proxy;
0047 
0048     //! Counter preventing the observer from being destroyed while in use by the scheduler.
0049     /** Valid only when observation is on. **/
0050     atomic<intptr_t> my_busy_count;
0051 
0052 public:
0053     //! Enable or disable observation
0054     /** For local observers the method can be used only when the current thread
0055         has the task scheduler initialized or is attached to an arena.
0056 
0057         Repeated calls with the same state are no-ops. **/
0058     void __TBB_EXPORTED_METHOD observe( bool state=true );
0059 
0060     //! Returns true if observation is enabled, false otherwise.
0061     bool is_observing() const {return my_proxy!=NULL;}
0062 
0063     //! Construct observer with observation disabled.
0064     task_scheduler_observer_v3() : my_proxy(NULL) { my_busy_count.store<relaxed>(0); }
0065 
0066     //! Entry notification
0067     /** Invoked from inside observe(true) call and whenever a worker enters the arena
0068         this observer is associated with. If a thread is already in the arena when
0069         the observer is activated, the entry notification is called before it
0070         executes the first stolen task.
0071 
0072         Obsolete semantics. For global observers it is called by a thread before
0073         the first steal since observation became enabled. **/
0074     virtual void on_scheduler_entry( bool /*is_worker*/ ) {}
0075 
0076     //! Exit notification
0077     /** Invoked from inside observe(false) call and whenever a worker leaves the
0078         arena this observer is associated with.
0079 
0080         Obsolete semantics. For global observers it is called by a thread before
0081         the first steal since observation became enabled. **/
0082     virtual void on_scheduler_exit( bool /*is_worker*/ ) {}
0083 
0084     //! Destructor automatically switches observation off if it is enabled.
0085     virtual ~task_scheduler_observer_v3() { if(my_proxy) observe(false);}
0086 };
0087 
0088 } // namespace internal
0089 
0090 #if __TBB_ARENA_OBSERVER
0091 namespace interface6 {
0092 class task_scheduler_observer : public internal::task_scheduler_observer_v3 {
0093     friend class internal::task_scheduler_observer_v3;
0094     friend class internal::observer_proxy;
0095     friend class internal::observer_list;
0096 
0097     /** Negative numbers with the largest absolute value to minimize probability
0098         of coincidence in case of a bug in busy count usage. **/
0099     // TODO: take more high bits for version number
0100     static const intptr_t v6_trait = (intptr_t)((~(uintptr_t)0 >> 1) + 1);
0101 
0102     //! contains task_arena pointer or tag indicating local or global semantics of the observer
0103     intptr_t my_context_tag;
0104     enum { global_tag = 0, implicit_tag = 1 };
0105 
0106 public:
0107     //! Construct local or global observer in inactive state (observation disabled).
0108     /** For a local observer entry/exit notifications are invoked whenever a worker
0109         thread joins/leaves the arena of the observer's owner thread. If a thread is
0110         already in the arena when the observer is activated, the entry notification is
0111         called before it executes the first stolen task. **/
0112     /** TODO: Obsolete.
0113         Global observer semantics is obsolete as it violates master thread isolation
0114         guarantees and is not composable. Thus the current default behavior of the
0115         constructor is obsolete too and will be changed in one of the future versions
0116         of the library. **/
0117     explicit task_scheduler_observer( bool local = false ) {
0118 #if  __TBB_ARENA_OBSERVER
0119         my_context_tag = local? implicit_tag : global_tag;
0120 #else
0121         __TBB_ASSERT_EX( !local, NULL );
0122         my_context_tag = global_tag;
0123 #endif
0124     }
0125 
0126 #if  __TBB_ARENA_OBSERVER
0127     //! Construct local observer for a given arena in inactive state (observation disabled).
0128     /** entry/exit notifications are invoked whenever a thread joins/leaves arena.
0129         If a thread is already in the arena when the observer is activated, the entry notification
0130         is called before it executes the first stolen task. **/
0131     explicit task_scheduler_observer( task_arena & a) {
0132         my_context_tag = (intptr_t)&a;
0133     }
0134 #endif /* __TBB_ARENA_OBSERVER */
0135 
0136     /** Destructor protects instance of the observer from concurrent notification.
0137        It is recommended to disable observation before destructor of a derived class starts,
0138        otherwise it can lead to concurrent notification callback on partly destroyed object **/
0139     virtual ~task_scheduler_observer() { if(my_proxy) observe(false); }
0140 
0141     //! Enable or disable observation
0142     /** Warning: concurrent invocations of this method are not safe.
0143         Repeated calls with the same state are no-ops. **/
0144     void observe( bool state=true ) {
0145         if( state && !my_proxy ) {
0146             __TBB_ASSERT( !my_busy_count, "Inconsistent state of task_scheduler_observer instance");
0147             my_busy_count.store<relaxed>(v6_trait);
0148         }
0149         internal::task_scheduler_observer_v3::observe(state);
0150     }
0151 };
0152 
0153 } //namespace interface6
0154 using interface6::task_scheduler_observer;
0155 #else /*__TBB_ARENA_OBSERVER*/
0156 typedef tbb::internal::task_scheduler_observer_v3 task_scheduler_observer;
0157 #endif /*__TBB_ARENA_OBSERVER*/
0158 
0159 } // namespace tbb
0160 
0161 #endif /* __TBB_SCHEDULER_OBSERVER */
0162 
0163 #include "internal/_warning_suppress_disable_notice.h"
0164 #undef __TBB_task_scheduler_observer_H_include_area
0165 
0166 #endif /* __TBB_task_scheduler_observer_H */