lolofon lolofon - 3 months ago 18
C++ Question

C++ threads does not work as I expect?

I am making bigger program where I want to use threads so as first I am trying to find out how threads actually work so I created a simple program and I can not understand why I do not get a message

"Bomberman has just put a bomb. Wait for the boom."
earlier than
"The bomb has just detonated."
.

Can anyone instruct me why is it not working as I expect?

#include <unistd.h>
#include <chrono>
#include <iostream>
#include <thread>

using namespace std;

class CBomberman;

class CBomb {
public:
CBomb(void) : m_Owner(nullptr) {
thread other_thread(&CBomb::Timer, this);
other_thread.join();
}

private:
void Timer(void) {
this_thread::sleep_for(chrono::seconds(3));
cout << "The bomb has just detonated." << endl;
}

CBomberman* m_Owner;
};

class CBomberman {
public:
CBomberman(void) : m_Bomb(nullptr) {}

bool PutBomb(void) {
if (m_Bomb == nullptr) {
m_Bomb = new CBomb();
delete m_Bomb;
return true;
} else {
cout << "The bomb has already been put." << endl;
return false;
}
}

private:
CBomb* m_Bomb;
};

int main() {
CBomberman bomberman;

bomberman.PutBomb();
cout << "Bomberman has just put a bomb. Wait for the boom." << endl;

return 0;
}

Answer

Your problem is that you're joining the thread immediately after you create it, meaning that you're only using multithreading in a very technical sense: you've definitely created another thread, and it's (probably) going to operate on another CPU core, but the host thread is simply sitting idle while the other thread works.

You need to locally store the thread object so that you can join it at a later point.

class CBomb
{
public:
    CBomb ( void )
    : m_Owner ( nullptr ),
    bomb_thread(&CBomb::Timer, this)
    {
    }
    std::thread bomb_thread; //This needs to be a member of this object. Whether you make it public or not is a matter of your design approach.
private:
    void Timer ( void )
    {
        this_thread::sleep_for( chrono::seconds( 3 ) );
        cout << "The bomb has just detonated." << endl;
    }

    CBomberman * m_Owner;
};

class CBomberman
{
public:
    CBomberman ( void )
    : m_Bomb ( nullptr )
    {

    }

    bool PutBomb ( void )
    {
        if( m_Bomb == nullptr )
        {
            m_Bomb = new CBomb();//Don't delete the object immediately after creating it. What were you expecting to have happen if you did?
            return true;
        }
        else
        {
            cout << "The bomb has already been put." << endl;
            return false;
        }
    }
    CBomb * m_Bomb;
};

int main()
{
    CBomberman bomberman;

    bomberman.PutBomb();
    cout << "Bomberman has just put a bomb. Wait for the boom." << endl;
    bomberman.m_bomb->bomb_thread.join(); //If we hit the end before the thread concludes, there could be some errors.

    return 0;
}