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.