I am working on a little 2D game engine right now and to make my life easier I took a look into the boost libraries. Especially boost::thread, which I’m going to write about and boost::statechart.
As I said before, I’m talking about boost::thread today and I assume that you have some C++ knowledge. I will create 2 classes. One class which creates the threads, a second class which inherits the threads. Finally in the main function we will use them.
The first thing you have to do is to include the boost header for boost::thread. In this case it is
Create a new file with a class inside, this time we call it BoostThread. Create a constructor and a virtual deconstructor, which you leave empty. For the constructor we create a private variable stopRequest and use it as inheritance for the constructor. As next we have to use the boost library. In the private part, create a boost::shared_ptr< boost::thread > newThread member.
1
2
3
4
5
6
7
8
9
10
| class BoostThread {
public:
BoostThread() : stopRequest( false ) { }
virtual ~BoostThread() {
virtual void run() { } // execute the new thread inside here
private:
bool stopRequest;
boost::shared_ptr< boost::thread > newThread;
}; |
This is now a part of the basis we need to create a new thread.
We can not run it yet, because there are 2 functions missing.
Create int start() and int stop() as public functions. start()
has to look like this:
assert( !newThread );
printf( “starting boost thread\n” );
newThread = boost::shared_ptr< boost::thread >( new boost::thread( boost::bind( &BoostThread::run, this ) ) );
return 0;
The line newThread = boost::share…. creates a shard_ptr as you can see and binds BoostThread::run into it. Which means if you call the function start(), the thread will be created and executed. If you want a function with parameters such as start( string fileName ) you just create this function, a string as private variable and instead of boost::bind( &BoostThread::run, this ) you write boost::bind( &BoostThread::run, this, myVariable );
For stop() you write:
assert( newThread );
stopRequest = true;
newThread–>join();
return 0;
This will cause the thread to stop.
The class should now look like this:
class BoostThread {
public:
BoostThread() : stopRequest( false ) { }
virtual ~BoostThread() {
virtual void run() { } // execute the new thread inside here
int start() {
assert( !newThread );
printf( "starting boost thread\n" );
newThread = boost::shared_ptr< boost::thread >( new boost::thread( boost::bind( &BoostThread::run, this ) ) );
return 0;
}
int stop() {
assert( newThread );
stopRequest = true;
newThread->join();
return 0;
}
private:
bool stopRequest;
boost::shared_ptr< boost::thread >; newThread;
};
This is it so far for the FIRST part.
Create a new class and I just call it TestClass. Inherit the BoostThread and create a constructor, the run function we have to inherit and one function called testFunction. Create a BoostThread *newThread as a private member.
class TestClass : public BoostThread {
public:
TestClass() { cout < < "Initializing a new Testclass" << endl; }
// import run from BoostThread to create a new thread
void run();
bool testFunction();
private:
// create a BoostThread member
BoostThread *newThread;
}
Ok, this is the class part so far. Now testFunction, run and the constructor need some code to run with. If you want you can leave the constructor empty, it is not important in this case. But I like to have a simple message for debug purposes so we write just cout < < "Initialize TestFunction\n"; inside.
For the run() function we do the same in this case. We write a simple message and that's it in this case. If you want you can execute sound code, network code or anything else inside this run function.
NOW the interesting part. The testFunction() turns out to start the thread. So we want to create now our newThread and execute the start() function from our BoostThread class.
bool TestClass::testFunction() {
newThread = new TestClass();
newThread->start();
return false;
}
The whole class code looks like this:
class TestClass : public BoostThread {
public:
TestClass() { cout < < "Initializing a new Testclass" << endl; }
// import run from BoostThread to create a new thread
void run();
bool testFunction();
private:
// create a BoostThread member
BoostThread *newThread;
};
void TestClass::run() {
cout << "Running a new thread\n"; }
}
bool TestClass::testFunction() {
newThread = new TestClass();
newThread->start();
return false;
}
The last part is very simple. I just created a main function, with a simple for loop and create threads inside the loop.
int main() {
// our test
TestClass newClass;
// loop 10x and execute each time a new thread
for( int i = 0; i < 10; i++ )
newClass.testFunction();
return 0;
}