-1

I am beginning to use the thread class.

  • In the main() thread below, an Example class is created.
  • Inside the constructor of Example, two threads are created in the Example::start() function.
  • Example::foo() is designed to print a message every second.
  • Example::bar() is designed to print a message every 5 seconds.
  • Inside the main() function, a loop is designed to print every 3 seconds.
  • I decided to not use join() in Example::start() because I would like to have the main() function continuously run.

Why does the main thread crash during run-time?

// thread example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <chrono>         // std::chrono::seconds
using namespace std;

class Example
{
    public:
        Example();
        void start();
        void foo();
        void bar(int x);
};

Example::Example()
{
    start();
}

void Example::start()
{
    std::thread first (&Example::foo, this);     // spawn new thread that calls foo()
    std::thread second (&Example::bar, this, 5);  // spawn new thread that calls bar(0)

    // synchronize threads:
    //first.join();                // pauses until first finishes
    //second.join();               // pauses until second finishes
}

void Example::foo()
{
    cout << "entered foo()" << endl;
    int count = 0;
      while(1)      {
        std::this_thread::sleep_for (std::chrono::seconds(1));
        ++count;
        cout << "foo() count = " << count << endl;
      }
}

void Example::bar(int x)
{
    cout << "entered bar() x = " << x << endl;
    int count = 0;
    while(1)    {
        std::this_thread::sleep_for (std::chrono::seconds(5));
        ++count;
        cout << "bar() count = " << count << endl;
    }
}

int main() {

  Example* c = new Example();
  cout << "Example() created" << endl;

  while(true) {
     std::this_thread::sleep_for(std::chrono::seconds(3));
     cout << "main() thread loop..." << endl;
  }

  std::cout << "end of main()";
  delete c;

  return 0;
}
code
  • 5,294
  • 16
  • 62
  • 113

2 Answers2

3

Foo::Start() initalizes two threads, thread Foo and thread bar. When the function Start returns to the main thread, the two thread objects go out of scope and the destructor is called for clearing out of scope variables.

A simple solution would be to make threads part of the class.

On another note, std::cout is not a synchronized class, when writing your text might be garbled: Is cout synchronized/thread-safe?

Also, when creating your class Example, delete is never called which causes a memory leak.

Community
  • 1
  • 1
  • Thank you Robert. When the two thread objects go out of scope and the destructor is called for clearing out of scope variables, what does that do? Does that attempt to "delete" the threads since they are not detached? Also - thank you for the std::cout synchronized class link. – code Aug 13 '14 at 00:01
  • See here for what the destructor calls for std::thread. http://www.cplusplus.com/reference/thread/thread/~thread/ – C_Plus_Plus_Programmer Aug 13 '14 at 00:20
1

Your comment here:

void Example::start()
{
    std::thread first (&Example::foo, this);     // spawn new thread that calls foo()
    std::thread second (&Example::bar, this, 5);  // spawn new thread that calls bar(0)

    // synchronize threads:
    //first.join();                // pauses until first finishes
    //second.join();               // pauses until second finishes
}

Is wrong.
Not only does the the join pause until the threads finish. But they also allow the thread to be cleaned up. A thread destructor calls terminate while the thread is join-able (ie it is still running). So you must call join() on the thread (to wait for it to finish) before you can allow the destructor to be called.

One of the comments above suggests calling detach(). This detaches the thread of execution from the thread object (thus making it not join-able). This will work (as your code is in infinite loop), but is a bad idea generally. As allowing main() to exit while threads are still running is undefined behavior.

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • Thank you @Loki . detach() fixed it! If using join() pauses until the thread finishes, and detach() detaches the thread from the thread object, then what kind of behavior happens when neither join() nor detach() is used? – code Aug 12 '14 at 23:58
  • So, if a thread invokes detach() - it is no longer joinable. How can a detached thread be destroyed? Does it need to be "deleted" manually (Ex: delete first;) ? – code Aug 12 '14 at 23:59
  • @user1456962: When the "thread of execution" of a detached thread finishes the function it started it will tidy up all the appropriate thread resources automatically. BUT note that if `main()` exits while detached threads are still running its undefined behavior. – Martin York Aug 13 '14 at 04:35