23 #if __TBB_SCHEDULER_OBSERVER 34 padded<observer_list> the_global_observer_list;
37 static atomic<int> observer_proxy_count;
39 struct check_observer_proxy_count {
40 ~check_observer_proxy_count() {
41 if( observer_proxy_count!=0 ) {
42 runtime_warning(
"Leaked %ld observer_proxy objects\n",
long(observer_proxy_count) );
47 static check_observer_proxy_count the_check_observer_proxy_count;
50 #if __TBB_ARENA_OBSERVER 51 interface6::task_scheduler_observer* observer_proxy::get_v6_observer() {
52 if(my_version != 6)
return NULL;
53 return static_cast<interface6::task_scheduler_observer*>(my_observer);
57 #if __TBB_ARENA_OBSERVER 58 bool observer_proxy::is_global() {
63 observer_proxy::observer_proxy( task_scheduler_observer_v3& tso )
64 : my_list(NULL), my_next(NULL), my_prev(NULL), my_observer(&tso)
67 ++observer_proxy_count;
72 #if __TBB_ARENA_OBSERVER 73 load<relaxed>(my_observer->my_busy_count)
77 __TBB_ASSERT( my_version >= 6 || !load<relaxed>(my_observer->my_busy_count), NULL );
81 observer_proxy::~observer_proxy () {
82 __TBB_ASSERT( !my_ref_count,
"Attempt to destroy proxy still in use" );
86 --observer_proxy_count;
90 template<memory_semantics M,
class T,
class V>
91 T atomic_fetch_and_store ( T*
addr,
const V& val ) {
92 return (T)atomic_traits<
sizeof(T), M>::fetch_and_store(
addr, (T)val );
95 void observer_list::clear () {
96 __TBB_ASSERT(
this != &the_global_observer_list,
"Method clear() cannot be used on the list of global observers" );
101 scoped_lock
lock(mutex(),
true);
102 observer_proxy *next = my_head;
103 while ( observer_proxy *
p = next ) {
108 task_scheduler_observer_v3 *obs =
p->my_observer;
111 if ( !obs || !(
p = (observer_proxy*)__TBB_FetchAndStoreW(&obs->my_proxy, 0)) )
115 __TBB_ASSERT( is_alive(
p->my_ref_count),
"Observer's proxy died prematurely" );
116 __TBB_ASSERT(
p->my_ref_count == 1,
"Reference for observer is missing" );
118 p->my_observer = NULL;
129 void observer_list::insert ( observer_proxy*
p ) {
130 scoped_lock
lock(mutex(),
true);
132 p->my_prev = my_tail;
133 my_tail->my_next =
p;
140 void observer_list::remove ( observer_proxy*
p ) {
141 __TBB_ASSERT( my_head,
"Attempt to remove an item from an empty list" );
142 __TBB_ASSERT( !my_tail->my_next,
"Last item's my_next must be NULL" );
145 my_tail =
p->my_prev;
149 p->my_next->my_prev =
p->my_prev;
151 if (
p == my_head ) {
153 my_head =
p->my_next;
157 p->my_prev->my_next =
p->my_next;
159 __TBB_ASSERT( (my_head && my_tail) || (!my_head && !my_tail), NULL );
162 void observer_list::remove_ref( observer_proxy*
p ) {
163 int r =
p->my_ref_count;
167 int r_old =
p->my_ref_count.compare_and_swap(r-1,r);
178 observer_list::scoped_lock
lock(mutex(),
true);
179 r = --
p->my_ref_count;
188 void observer_list::do_notify_entry_observers( observer_proxy*&
last,
bool worker ) {
190 observer_proxy *
p =
last, *prev =
p;
192 task_scheduler_observer_v3* tso=NULL;
195 scoped_lock
lock(mutex(),
false);
199 if( observer_proxy* q =
p->my_next ) {
201 remove_ref_fast(prev);
227 tso =
p->my_observer;
230 ++tso->my_busy_count;
239 tso->on_scheduler_entry(worker);
241 intptr_t bc = --tso->my_busy_count;
247 void observer_list::do_notify_exit_observers( observer_proxy*
last,
bool worker ) {
249 observer_proxy *
p = NULL, *prev = NULL;
251 task_scheduler_observer_v3* tso=NULL;
254 scoped_lock
lock(mutex(),
false);
259 __TBB_ASSERT(
p->my_next,
"List items before 'last' must have valid my_next pointer" );
261 remove_ref_fast(prev);
275 __TBB_ASSERT(
p,
"Nonzero 'last' must guarantee that the global list is non-empty" );
277 tso =
p->my_observer;
282 ++tso->my_busy_count;
290 tso->on_scheduler_exit(worker);
292 intptr_t bc = --tso->my_busy_count;
303 #if __TBB_ARENA_OBSERVER 308 intptr_t tag =
my_proxy->get_v6_observer()->my_context_tag;
310 task_arena *a = reinterpret_cast<task_arena*>(tag);
312 my_proxy->my_list = &a->my_arena->my_observers;
314 if( !(
s &&
s->my_arena) )
318 my_proxy->my_list = &
s->my_arena->my_observers;
322 if(
s && &
s->my_arena->my_observers ==
my_proxy->my_list )
323 my_proxy->my_list->notify_entry_observers(
s->my_last_local_observer,
s->is_worker() );
330 my_proxy->my_list = &the_global_observer_list;
335 the_global_observer_list.notify_entry_observers(
s->my_last_global_observer,
s->is_worker() );
345 __TBB_ASSERT( is_alive(proxy->my_ref_count),
"Observer's proxy died prematurely" );
346 __TBB_ASSERT( proxy->my_ref_count >= 1,
"reference for observer missing" );
350 observer_list::scoped_lock
lock(list.mutex(),
true);
351 proxy->my_observer = NULL;
353 if( !--proxy->my_ref_count ) {
void __TBB_EXPORTED_FUNC runtime_warning(const char *format,...)
Report a runtime warning.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
static const int automatic
Typedef for number of threads that is automatic.
friend class observer_proxy
static generic_scheduler * local_scheduler_if_initialized()
#define __TBB_ASSERT_EX(predicate, comment)
"Extended" version is useful to suppress warnings if a variable is only used with an assert
void const char const char int ITT_FORMAT __itt_group_sync p
auto last(Container &c) -> decltype(begin(c))
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
static bool initialization_done()
static const intptr_t v6_trait
observer_proxy * my_proxy
Pointer to the proxy holding this observer.
void DoOneTimeInitializations()
Performs thread-safe lazy one-time general TBB initialization.
void poison_pointer(T *__TBB_atomic &)
void const char const char int ITT_FORMAT __itt_group_sync s
void __TBB_EXPORTED_METHOD observe(bool state=true)
Enable or disable observation.
friend class observer_list
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.
atomic< intptr_t > my_busy_count
Counter preventing the observer from being destroyed while in use by the scheduler.