|
| 1 | +--- a/src/tbb/include/oneapi/tbb/task_scheduler_observer.h |
| 2 | ++++ b/src/tbb/include/oneapi/tbb/task_scheduler_observer.h |
| 3 | +@@ -17,10 +17,13 @@ |
| 4 | + #ifndef __TBB_task_scheduler_observer_H |
| 5 | + #define __TBB_task_scheduler_observer_H |
| 6 | + |
| 7 | ++#include <atomic> |
| 8 | ++ |
| 9 | + #include "detail/_namespace_injection.h" |
| 10 | ++ |
| 11 | + #include "task_arena.h" |
| 12 | +-#include <atomic> |
| 13 | + |
| 14 | ++ |
| 15 | + namespace tbb { |
| 16 | + namespace detail { |
| 17 | + |
| 18 | +@@ -112,5 +115,128 @@ |
| 19 | + } |
| 20 | + } // namespace tbb |
| 21 | + |
| 22 | ++ |
| 23 | ++// Provided for backwards compatibility. This is a local addition, not part of |
| 24 | ++// upstream oneTBB, so the tbb.dll stub built by src/install.libs.R must be |
| 25 | ++// able to tell whether the TBB headers in use supply these declarations (the |
| 26 | ++// bundled copy does) or whether it has to declare them itself (as with the |
| 27 | ++// pristine headers shipped by Rtools). |
| 28 | ++#define __TBB_LEGACY_TASK_SCHEDULER_OBSERVER_PROVIDED 1 |
| 29 | ++ |
| 30 | ++namespace tbb { |
| 31 | ++namespace interface6 { |
| 32 | ++class task_scheduler_observer; |
| 33 | ++} |
| 34 | ++namespace internal { |
| 35 | ++ |
| 36 | ++class task_scheduler_observer_v3 { |
| 37 | ++ friend class tbb::detail::r1::observer_proxy; |
| 38 | ++ friend class tbb::detail::r1::observer_list; |
| 39 | ++ friend class interface6::task_scheduler_observer; |
| 40 | ++ |
| 41 | ++ //! Pointer to the proxy holding this observer. |
| 42 | ++ /** Observers are proxied by the scheduler to maintain persistent lists of them. **/ |
| 43 | ++ tbb::detail::r1::observer_proxy* my_proxy; |
| 44 | ++ |
| 45 | ++ //! Counter preventing the observer from being destroyed while in use by the scheduler. |
| 46 | ++ /** Valid only when observation is on. **/ |
| 47 | ++ std::atomic<intptr_t> my_busy_count; |
| 48 | ++ |
| 49 | ++public: |
| 50 | ++ //! Enable or disable observation |
| 51 | ++ /** For local observers the method can be used only when the current thread |
| 52 | ++ has the task scheduler initialized or is attached to an arena. |
| 53 | ++ |
| 54 | ++ Repeated calls with the same state are no-ops. **/ |
| 55 | ++ void __TBB_EXPORTED_METHOD observe( bool state=true ); |
| 56 | ++ |
| 57 | ++ //! Returns true if observation is enabled, false otherwise. |
| 58 | ++ bool is_observing() const {return my_proxy!=NULL;} |
| 59 | ++ |
| 60 | ++ //! Construct observer with observation disabled. |
| 61 | ++ task_scheduler_observer_v3() : my_proxy(NULL) { my_busy_count.store(0); } |
| 62 | ++ |
| 63 | ++ //! Entry notification |
| 64 | ++ /** Invoked from inside observe(true) call and whenever a worker enters the arena |
| 65 | ++ this observer is associated with. If a thread is already in the arena when |
| 66 | ++ the observer is activated, the entry notification is called before it |
| 67 | ++ executes the first stolen task. |
| 68 | ++ |
| 69 | ++ Obsolete semantics. For global observers it is called by a thread before |
| 70 | ++ the first steal since observation became enabled. **/ |
| 71 | ++ virtual void on_scheduler_entry( bool /*is_worker*/ ) {} |
| 72 | ++ |
| 73 | ++ //! Exit notification |
| 74 | ++ /** Invoked from inside observe(false) call and whenever a worker leaves the |
| 75 | ++ arena this observer is associated with. |
| 76 | ++ |
| 77 | ++ Obsolete semantics. For global observers it is called by a thread before |
| 78 | ++ the first steal since observation became enabled. **/ |
| 79 | ++ virtual void on_scheduler_exit( bool /*is_worker*/ ) {} |
| 80 | ++ |
| 81 | ++ //! Destructor automatically switches observation off if it is enabled. |
| 82 | ++ virtual ~task_scheduler_observer_v3() { if(my_proxy) observe(false);} |
| 83 | ++}; |
| 84 | ++ |
| 85 | ++} // namespace internal |
| 86 | ++ |
| 87 | ++namespace interface6 { |
| 88 | ++class task_scheduler_observer : public internal::task_scheduler_observer_v3 { |
| 89 | ++ friend class internal::task_scheduler_observer_v3; |
| 90 | ++ friend class tbb::detail::r1::observer_proxy; |
| 91 | ++ friend class tbb::detail::r1::observer_list; |
| 92 | ++ |
| 93 | ++ /** Negative numbers with the largest absolute value to minimize probability |
| 94 | ++ of coincidence in case of a bug in busy count usage. **/ |
| 95 | ++ // TODO: take more high bits for version number |
| 96 | ++ static const intptr_t v6_trait = (intptr_t)((~(uintptr_t)0 >> 1) + 1); |
| 97 | ++ |
| 98 | ++ //! contains task_arena pointer or tag indicating local or global semantics of the observer |
| 99 | ++ intptr_t my_context_tag; |
| 100 | ++ enum { global_tag = 0, implicit_tag = 1 }; |
| 101 | ++ |
| 102 | ++public: |
| 103 | ++ //! Construct local or global observer in inactive state (observation disabled). |
| 104 | ++ /** For a local observer entry/exit notifications are invoked whenever a worker |
| 105 | ++ thread joins/leaves the arena of the observer's owner thread. If a thread is |
| 106 | ++ already in the arena when the observer is activated, the entry notification is |
| 107 | ++ called before it executes the first stolen task. **/ |
| 108 | ++ /** TODO: Obsolete. |
| 109 | ++ Global observer semantics is obsolete as it violates master thread isolation |
| 110 | ++ guarantees and is not composable. Thus the current default behavior of the |
| 111 | ++ constructor is obsolete too and will be changed in one of the future versions |
| 112 | ++ of the library. **/ |
| 113 | ++ explicit task_scheduler_observer( bool local = false ) { |
| 114 | ++ my_context_tag = local? implicit_tag : global_tag; |
| 115 | ++ } |
| 116 | ++ |
| 117 | ++ //! Construct local observer for a given arena in inactive state (observation disabled). |
| 118 | ++ /** entry/exit notifications are invoked whenever a thread joins/leaves arena. |
| 119 | ++ If a thread is already in the arena when the observer is activated, the entry notification |
| 120 | ++ is called before it executes the first stolen task. **/ |
| 121 | ++ explicit task_scheduler_observer( task_arena & a) { |
| 122 | ++ my_context_tag = (intptr_t)&a; |
| 123 | ++ } |
| 124 | ++ |
| 125 | ++ /** Destructor protects instance of the observer from concurrent notification. |
| 126 | ++ It is recommended to disable observation before destructor of a derived class starts, |
| 127 | ++ otherwise it can lead to concurrent notification callback on partly destroyed object **/ |
| 128 | ++ virtual ~task_scheduler_observer() { if(my_proxy) observe(false); } |
| 129 | ++ |
| 130 | ++ //! Enable or disable observation |
| 131 | ++ /** Warning: concurrent invocations of this method are not safe. |
| 132 | ++ Repeated calls with the same state are no-ops. **/ |
| 133 | ++ void observe( bool state=true ) { |
| 134 | ++ if( state && !my_proxy ) { |
| 135 | ++ __TBB_ASSERT( !my_busy_count, "Inconsistent state of task_scheduler_observer instance"); |
| 136 | ++ my_busy_count.store(v6_trait); |
| 137 | ++ } |
| 138 | ++ internal::task_scheduler_observer_v3::observe(state); |
| 139 | ++ } |
| 140 | ++}; |
| 141 | ++ |
| 142 | ++} //namespace interface6 |
| 143 | ++ |
| 144 | ++} // namespace tbb |
| 145 | + |
| 146 | + #endif /* __TBB_task_scheduler_observer_H */ |
| 147 | +--- a/src/tbb/src/tbb/observer_proxy.cpp |
| 148 | ++++ b/src/tbb/src/tbb/observer_proxy.cpp |
| 149 | +@@ -317,3 +317,23 @@ |
| 150 | + } // namespace r1 |
| 151 | + } // namespace detail |
| 152 | + } // namespace tbb |
| 153 | ++ |
| 154 | ++// Not on Windows: there the old ABI is published by the tbb.dll stub built |
| 155 | ++// from src/tbb-compat/tbb-compat.cpp, which has to define this itself in |
| 156 | ++// order for R CMD SHLIB to pick it up when generating the export list. |
| 157 | ++// Defining it here as well makes the stub fail to link with "multiple |
| 158 | ++// definition of tbb::internal::task_scheduler_observer_v3::observe". |
| 159 | ++#ifndef _WIN32 |
| 160 | ++ |
| 161 | ++namespace tbb { |
| 162 | ++namespace internal { |
| 163 | ++ |
| 164 | ++void __TBB_EXPORTED_FUNC task_scheduler_observer_v3::observe( bool enable ) { |
| 165 | ++ auto* tso = (tbb::detail::d1::task_scheduler_observer*) (this); |
| 166 | ++ tbb::detail::r1::observe(*tso, enable); |
| 167 | ++} |
| 168 | ++ |
| 169 | ++} // namespace internal |
| 170 | ++} // namespace tbb |
| 171 | ++ |
| 172 | ++#endif /* _WIN32 */ |
| 173 | +\ No newline at end of file |
0 commit comments