I'm having a hard time understanding TBB's enumerable thread specific. I have written this little code to test the TLS
#include <iostream>
#include <vector>
#include "tbb/task_scheduler_init.h"
#include "tbb/enumerable_thread_specific.h"
#include "tbb/task.h"
typedef tbb::enumerable_thread_specific< std::vector<int> > TLS;
class Child: public tbb::task {
private:
int start;
int limit;
TLS* local_tls;
public:
Child( int s_, int l_, TLS* t_):start(s_),limit(l_),local_tls(t_){}
virtual ~Child(){
local_tls=0;
}
tbb::task* execute(){
TLS::reference local_vector = local_tls->local();
for(int i=start; i<limit;++i){
local_vector.push_back( i );
}
}
return 0;
}
};
class Cont: public tbb::task {
private:
TLS global_tls;
public:
Cont(){}
virtual ~Cont(){}
TLS* GetTls(void) { return &global_tls; }
tbb::task* execute(){
TLS::const_iterator it( global_tls.begin() );
const TLS::const_iterator end( global_tls.end() );
std::cout << "ETS.SIZE: " << global_tls.size() << std::endl;
while( it != end ) {
std::cout << "*ITSIZE: " << (*it).size() << "\n";
for( unsigned int j(0); j < (*it).size(); ++j ) {
std::cout << (*it)[j] << " " << std::endl;
}
++it;
}
return 0;
}
};
class Root: public tbb::task {
private:
public:
Root(){}
virtual ~Root(){}
tbb::task* execute(){
tbb::task_list l;
Cont& c = *new ( allocate_continuation() ) Cont();
l.push_back( (*new ( c.allocate_child() ) Child(0,10,c.GetTls()) ) );
l.push_back( (*new ( c.allocate_child() ) Child(11,21,c.GetTls()) ) );
c.set_ref_count( 2 );
c.spawn( l );
return 0;
}
};
int main(void) {
Root& r = *new(tbb::task::allocate_root()) Root( );
tbb::task::spawn_root_and_wait( r );
return 0;
}
but the output is awkward. Sometimes is:
ETS.SIZE: 2
*ITSIZE: 10
0 1 2 3 4 5 6 7 8 9
*ITSIZE: 10
11 12 13 14 15 16 17 18 19 20
and sometimes is:
ETS.SIZE: 1
*ITSIZE: 20
0 1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 20
Why does that change happens? Also, in the TBB forum I read that sometimes the TLS doesn't contain all of the expected values, but the reason for that is apparently the relationship about parent and child tasks. Didn't understand that too much, though.
Any help?
Thank you.
The 'awkward' output difference you see has nothing to do with enumerable_thread_specific
. It's just due to the Child
tasks being executed by two different threads (in the case 1) or the same thread (in the case 2).