Before we start the TBB journey, let's take a look at how to initialize and terminate the TBB library, after all, this is a basis for using TBB ~ ~ ~
The TBB provides a class:task_scheduler_init that initializes TBB in constructor and terminates the destructor library in TBB.
So we know the simplest way to initialize & terminate TBB:
1 #include "tbb/task_scheduler_init.h"
2 using namespace TBB;
3
4 int main () {
5 task_scheduler_init init;
6..
7 return 0;
8}
Thus, the constructor and destructor of Task_scheduler_init provide initialization and termination capabilities.
Let's look at the constructor of Task_scheduler_init, open header file:tbb/task_scheduler_init.h and find its constructor declaration:
1//!
Class representing reference to TBB scheduler. 2/** A thread must construct a task_scheduler_init, and keep it alive, 3 during the time that it uses the services O
F class task. 4 @ingroup task_scheduling */5 class Task_scheduler_init:internal::no_copy {6/** NULL if not currently init Ialized.
* * 7 internal::scheduler* My_scheduler; 8 Public:9//!
Typedef for number of threads the IS automatic.
10 static const INT automatic =-1; 11 12//!
Argument to initialize () or constructor this causes initialization to be deferred.
13 static const int deferred =-2; 14 15//! Ensure that scheduler exists to the thread 16/** A value of-1 lets TBB decide on the
threads, which is typically the number of hardware threads. For production code, the default value of-1 should to used, particularly if the client code is MI Xed and third party clients thaT might also use TBB. The number_of_threads is ignored if any other task_scheduler_inits currently exist.
A thread may construct multiple task_scheduler_inits. Doing so does no harm because the underlying scheduler is reference counted.
* * 25 void Initialize (int number_of_threads=automatic); 26 27//!
Inverse of method Initialize.
28 void Terminate (); 29 30//!
Shorthand for default constructor followed by call to Intialize (number_of_threads). 31 task_scheduler_init (int number_of_threads=automatic): My_scheduler (NULL) {Initialize (number
_of_threads); 33} 34 35//!
Destroy Scheduler for this thread if thread has no other live task_scheduler_inits.
36 ~task_scheduler_init () {Panax Notoginseng if (My_scheduler) terminate ();
Internal::p oison_pointer (My_scheduler); 40} 41};
We see that the constructor of Task_scheduler_init has a default parameter number_of_threads, the default value is automatic (-1), It means that the Initialize function is automatically invoked when constructor, and the thread scheduler is created.
Number_of_threads possible values include: Automatic ( -1): Automatically invoke the Initialize () function when constructor, creating the appropriate thread scheduler Deferred (-2): means not to invoke the Initialize () function initialization while consturctor, and wait until you manually initialize any positive integers: Specify the number of threads you want, and do not specify them yourself unless you have specifically tuned for the platform Of course, we can also use deferred to create, and then in Initialize (number_of_threads) to specify the number of threads
Let's look at a typical example of using deferred parameters to dynamically set:
1 int main (int argc, char* argv[]) {
2 int nthread = Strtol (argv[0],0,0);
3 task_scheduler_init init (task_scheduler_init::d eferred);
4 if (nthread>=1)
5 init.initialize (nthread);
6 //... code that uses Task Scheduler only if Nthread>=1
... 7 if (nthread>=1)
8 init.terminate ();
9 return 0;
10}
One should note that the construction of task_scheduler_init is time-consuming, do not create it every time you use TBB, but create one at main or at the entrance.
In the TBB in-depth section we will go to see how task_scheduler_init is implementing the thread Scheduler ~ ~ (to be continued)