#include <iostream>
#include <thread>
#include <chrono>
using namespace std;

// You need something to signal your thread that it should exit.
// So, we're using a global variable to store this information.

volatile bool is_exited = false;

// Here is our callback() or long running task that
// our threads would be executing

void callback()
{
    // This loop should exit once is_exited flag's condition is true.
    // This loop body is actually indicating the actual job that the
    // thread needs to execute.

    auto id = this_thread::get_id();
    
    cout << id << ". Started!\n";

    while( !is_exited )
    {
        cout << id << ". Hello!\n";
        this_thread::sleep_for( 100ms );
    }
    
    cout << id << ". Exited!\n";
}

// Here is our main() function that would start two threads,
// register the callback, and run it. After doing its own processing,
// the main() function would signal threads to stop and wait for them
// to finish their running task and get out of the callbacks. Usually,
// there's a join() or wait() function call to do this. C++ has join().

int main()
{
    cout << "main() started!\n";
	
    // Now, register your callback with your threads
    // C++ threads start right away after this
    // You don't have to call some start() function

    thread t1 { callback };
    thread t2 { callback };

    // So, now that the threads have started the main()
    // can do its own things

    //for ( int i = 0; i < 100000000; ++i )
    //{
    //    // ...
    //}

    this_thread::sleep_for( 1s );

    // Now, we need to send the signal to threads to stop their
    // execution for a graceful termination.

    is_exited = true;

    // There's a call to join() function to wait for the
    // threads to exit; so here the main() function is waiting
    // for the threads to exit. Once the callback() finishes,
    // the thread would exit and the main() function would get out
    // of these join() calls. And, the program would exit gracefully.

    t1.join();
    t2.join();

    cout << "main() exited!\n";

    return 0;
}