|
||||
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 */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |