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 ) {
static generic_scheduler * init_scheduler(int num_threads, stack_size_type stack_size, bool auto_init)
Processes scheduler initialization request (possibly nested) in a master thread.
auto last(Container &c) -> decltype(begin(c))
friend class observer_proxy
void const char const char int ITT_FORMAT __itt_group_sync p
static const intptr_t v6_trait
void __TBB_EXPORTED_METHOD observe(bool state=true)
Enable or disable observation.
#define __TBB_ASSERT_EX(predicate, comment)
"Extended" version is useful to suppress warnings if a variable is only used with an assert
static generic_scheduler * local_scheduler_if_initialized()
void DoOneTimeInitializations()
Performs thread-safe lazy one-time general TBB initialization.
void const char const char int ITT_FORMAT __itt_group_sync s
atomic< intptr_t > my_busy_count
Counter preventing the observer from being destroyed while in use by the scheduler.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
friend class observer_list
void poison_pointer(T *__TBB_atomic &)
static bool initialization_done()
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void * lock
observer_proxy * my_proxy
Pointer to the proxy holding this observer.
static const int automatic
Typedef for number of threads that is automatic.
void __TBB_EXPORTED_FUNC runtime_warning(const char *format,...)
Report a runtime warning.