2

So I have this class:

class foo {
public:
        foo() { };
        void me1() const {
            while(1) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 0;
            }
        }
        void me2() const {
            while(1) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 1;
            }
        }
private:
    std::mutex m;
};

Now I want to run this two methods in some two different threads, I do it like this:

int main() {

    foo myfoo;

    std::thread firstThread(&foo::me1, &myfoo);
    std::thread secondThread(&foo::me2, &myfoo);

    firstThread.detach();
    secondThread.detach();

    //while(1) { }

    return 0;
}

I don't want to wait for any of this two methods to finish, they will simultaneously run until the main thread will be killed.

Is it ok to have some kind of infinite-loop at the end of main thread? (like the commented while(1) {}).

Or should I call some kinda sleep function?

mariusmmg2
  • 713
  • 18
  • 37
  • what do you want main thread to do while the other threads are running? – alexm Dec 25 '15 at 21:35
  • 1
    If they will simultaneously run until the main thread is killed why don't you just simply wait for them? You will wait for them until they die, if the main thread is killed, both will die anyway. If both of them finish their execution, the main thread has no purpose anymore, so he can die. – Simone Zandara Dec 25 '15 at 21:35
  • @alexm some stuff that can't be done before that two threads are running. – mariusmmg2 Dec 25 '15 at 21:42
  • It's okay to have the infinite loop at the end but that would *not* achieve what it sounds like you're trying to (it's infinite). Whether or not you should use `sleep` or not seems opinion-based questioning though. – ChiefTwoPencils Dec 25 '15 at 21:42
  • @SimoneZandara so you are telling me to just `join` them both? but if I join let's say the first one, I will be unable to `join` the second one (because they will run forever). Or I first `detach` one, and then `join` the second one? – mariusmmg2 Dec 25 '15 at 21:44
  • You have an infinite loop in me1 and me2 , there is no need to wait for any of them in main. This is a noQ. – g24l Dec 25 '15 at 21:45
  • 1
    @MariusMarusanici In your question you say that you don't need to wait for them, when you join two threads, you simply wait for both of them to finish. So if one never ends, your main thread will never end until it's killed, I thought that it was you were asking. – Simone Zandara Dec 25 '15 at 21:46
  • 1
    @g24l If the main thread ends, the subthreads are killed as well so he needs to – Simone Zandara Dec 25 '15 at 21:49
  • 2
    Technically your loop may cause undefined behaviour: http://stackoverflow.com/q/3592557/212870 – Alan Stokes Dec 25 '15 at 21:49
  • More importantly, your main thread will be maxing out one core, wasting power and preventing more useful work from running. Any alternative is preferable to a busy wait. – Alan Stokes Dec 25 '15 at 21:51
  • @SimoneZandara I am just saying that he has no exit condition in his threads. – g24l Dec 25 '15 at 22:08
  • 1
    Omg , just remove those const specifiers from your function or make the mutex mutable , plz. – g24l Dec 26 '15 at 00:41

3 Answers3

3

You need to define an exit condition in your foo::me1() and foo::me2() . If you don't know how to do that, that

sleep(/*number of seconds you want your program to run*/ );

will do just fine.

If you define a termination clause then the bruteforce would be to expose something like an atomic:

class foo {
public:

std::atomic<int> me1done = false;
std::atomic<int> me2done = false;

        foo() { };
        void me1() {
            while(/* need exit condition here*/) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 0;
            }
            me1done = true;
        }
        void me2() {
            while(/*need exit condition here*/) {
                std::lock_guard<std::mutex> ldock(m);
                std::cout << 1;
            }
            me2done = true;
        }


private:
    std::mutex m;

};

and then you can check in main by polling every x-seconds.

int main(void)
{
// start your threads and detach

foo myfoo;

std::thread firstThread(&foo::me1, &myfoo);
std::thread secondThread(&foo::me2, &myfoo);

firstThread.detach();
secondThread.detach();

while( not (myfoo.me1done and myfoo.me2done ) )
{
sleep( /* some time */);
}

return 0;
}

If you want to be more elaborate you will have to work with condition variables.

g24l
  • 3,055
  • 15
  • 28
2

If you want to determine if the two threads have finished your best bet is actually not to detach() the threads but rather join() them before exiting the main thread. That is, you'd kick off both threads and they'll run concurrently and once kicked off you simply join() each. Of course, that assumes that the threads would terminate.

Having a detach()ed thread effectively means you can never be sure if it has finished. That is generally rarely useful and I consider it a mistake that detach() was added to std::thread. However, even with detach()ed thread you can recognize when an objective is achieved without a busy wait. To that end you'd set up suitable variables indicating completion or progress and have them protected by a std::mutex. The main thread would then wait() on a std::condition_variable which gets notify_once()ed by the respective thread upon the completion/progress update which would be done in reasonable intervals. Once all threads have indicated that they are done or have achieved a suitable objective the main() thread can finish.

Using a timer alone is generally not a good approach. The signalling between threads is typically preferable and tends to create a more responsive system. You can still used a timed version of wait() (i.e., wait_until() or wait_for()), e.g., to alert upon suspecting a somehow hung or timed-out thread.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
1

empty infinite loops as while(1) { } are UB.

adding a sleep inside is OK though.

To run infinitely foo::me1/foo::me2, you have several other choices:

int main()
{
    foo myfoo;

    std::thread firstThread(&foo::me1, &myfoo);
    std::thread secondThread(&foo::me2, &myfoo);

    firstThread.join();  // wait infinitely as it never ends.
    secondThread.join(); // and so never reach 
}

or simply use main thread to do one work:

int main()
{
    foo myfoo;

    std::thread firstThread(&foo::me1, &myfoo);
    myfoo.me2(); // work infinitely as it never ends.

    firstThread.join(); // and so never reach
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302