19 #if __TBB_SCHEDULER_OBSERVER
30 padded<observer_list> the_global_observer_list;
33 static atomic<int> observer_proxy_count;
35 struct check_observer_proxy_count {
36 ~check_observer_proxy_count() {
37 if( observer_proxy_count!=0 ) {
38 runtime_warning(
"Leaked %ld observer_proxy objects\n",
long(observer_proxy_count) );
43 static check_observer_proxy_count the_check_observer_proxy_count;
46 #if __TBB_ARENA_OBSERVER
47 interface6::task_scheduler_observer* observer_proxy::get_v6_observer() {
48 if(my_version != 6)
return NULL;
49 return static_cast<interface6::task_scheduler_observer*
>(my_observer);
53 #if __TBB_ARENA_OBSERVER
54 bool observer_proxy::is_global() {
59 observer_proxy::observer_proxy( task_scheduler_observer_v3& tso )
60 : my_list(NULL), my_next(NULL), my_prev(NULL), my_observer(&tso)
63 ++observer_proxy_count;
68 #if __TBB_ARENA_OBSERVER
69 load<relaxed>(my_observer->my_busy_count)
73 __TBB_ASSERT( my_version >= 6 || !load<relaxed>(my_observer->my_busy_count), NULL );
77 observer_proxy::~observer_proxy () {
78 __TBB_ASSERT( !my_ref_count,
"Attempt to destroy proxy still in use" );
82 --observer_proxy_count;
86 template<memory_semantics M,
class T,
class V>
87 T atomic_fetch_and_store ( T*
addr,
const V& val ) {
88 return (T)atomic_traits<
sizeof(T), M>::fetch_and_store(
addr, (T)val );
91 void observer_list::clear () {
92 __TBB_ASSERT(
this != &the_global_observer_list,
"Method clear() cannot be used on the list of global observers" );
97 scoped_lock
lock(mutex(),
true);
98 observer_proxy *next = my_head;
99 while ( observer_proxy *
p = next ) {
104 task_scheduler_observer_v3 *obs =
p->my_observer;
107 if ( !obs || !(
p = (observer_proxy*)__TBB_FetchAndStoreW(&obs->my_proxy, 0)) )
111 __TBB_ASSERT( is_alive(
p->my_ref_count),
"Observer's proxy died prematurely" );
112 __TBB_ASSERT(
p->my_ref_count == 1,
"Reference for observer is missing" );
114 p->my_observer = NULL;
125 void observer_list::insert ( observer_proxy*
p ) {
126 scoped_lock
lock(mutex(),
true);
128 p->my_prev = my_tail;
129 my_tail->my_next =
p;
136 void observer_list::remove ( observer_proxy*
p ) {
137 __TBB_ASSERT( my_head,
"Attempt to remove an item from an empty list" );
138 __TBB_ASSERT( !my_tail->my_next,
"Last item's my_next must be NULL" );
141 my_tail =
p->my_prev;
145 p->my_next->my_prev =
p->my_prev;
147 if (
p == my_head ) {
149 my_head =
p->my_next;
153 p->my_prev->my_next =
p->my_next;
155 __TBB_ASSERT( (my_head && my_tail) || (!my_head && !my_tail), NULL );
158 void observer_list::remove_ref( observer_proxy*
p ) {
159 int r =
p->my_ref_count;
163 int r_old =
p->my_ref_count.compare_and_swap(r-1,r);
174 observer_list::scoped_lock
lock(mutex(),
true);
175 r = --
p->my_ref_count;
184 void observer_list::do_notify_entry_observers( observer_proxy*&
last,
bool worker ) {
186 observer_proxy *
p =
last, *prev =
p;
188 task_scheduler_observer_v3* tso=NULL;
191 scoped_lock
lock(mutex(),
false);
195 if( observer_proxy* q =
p->my_next ) {
197 remove_ref_fast(prev);
223 tso =
p->my_observer;
226 ++tso->my_busy_count;
235 tso->on_scheduler_entry(worker);
237 intptr_t bc = --tso->my_busy_count;
243 void observer_list::do_notify_exit_observers( observer_proxy*
last,
bool worker ) {
245 observer_proxy *
p = NULL, *prev = NULL;
247 task_scheduler_observer_v3* tso=NULL;
250 scoped_lock
lock(mutex(),
false);
255 __TBB_ASSERT(
p->my_next,
"List items before 'last' must have valid my_next pointer" );
257 remove_ref_fast(prev);
271 __TBB_ASSERT(
p,
"Nonzero 'last' must guarantee that the global list is non-empty" );
273 tso =
p->my_observer;
278 ++tso->my_busy_count;
286 tso->on_scheduler_exit(worker);
288 intptr_t bc = --tso->my_busy_count;
299 #if __TBB_ARENA_OBSERVER
304 intptr_t tag =
my_proxy->get_v6_observer()->my_context_tag;
306 task_arena *a =
reinterpret_cast<task_arena*
>(tag);
307 if ( a->my_arena==NULL )
309 my_proxy->my_list = &a->my_arena->my_observers;
311 if( !(
s &&
s->my_arena) )
315 my_proxy->my_list = &
s->my_arena->my_observers;
319 if(
s && &
s->my_arena->my_observers ==
my_proxy->my_list )
320 my_proxy->my_list->notify_entry_observers(
s->my_last_local_observer,
s->is_worker() );
327 my_proxy->my_list = &the_global_observer_list;
332 the_global_observer_list.notify_entry_observers(
s->my_last_global_observer,
s->is_worker() );
342 __TBB_ASSERT( is_alive(proxy->my_ref_count),
"Observer's proxy died prematurely" );
343 __TBB_ASSERT( proxy->my_ref_count >= 1,
"reference for observer missing" );
347 observer_list::scoped_lock
lock(list.mutex(),
true);
348 proxy->my_observer = NULL;
350 if( !--proxy->my_ref_count ) {