Thread: Keeping main() waiting until a function returns

  1. #1
    Registered User
    Join Date
    Mar 2016
    Posts
    203

    Keeping main() waiting until a function returns

    I am reading about concurrency and trying to write a couple of small programs to test.
    Objective: launch a function waiter() in the background and another function, intruder(), in the foreground. While waiter() sleeps intruder() does its stuff and if it returns before waiter() awakes, waiter() holds up main() until it 'awakes', then waiter() returns and finally main() returns.
    Problem: (a) in main() if I declare waiter() first, as I should, it holds up intruder() as well, (b) if I create a std::thread object with waiter(), detach this thread, run intruder() and then thread.join() it throws std::system_error what(): Invalid argument
    Code:
    #include <iostream>
    #include <chrono>
    #include <thread>
    
    void waiter()
    {
        using namespace std::chrono_literals;
        std::this_thread::sleep_for(5s);
        std::cout << "Waited 5 secs!\n";
    };
    void intruder(){std::cout << "Cheeky me ;) \n";};
    
    int main()
    {
       waiter();
       // std::thread t(waiter);//throws std::system_error
       // t.detach();
        intruder();
        //t.join();
    }
    Also can the same objective be met with std::future and std::async? I wrote the following but calling get() on the std::future object returns waiter() immediately before 5 seconds are up and without it intruder() returns and then main() returns before waiter() can:
    Code:
    #include <iostream>
    #include <chrono>
    #include <future>
    
    void waiter(){ std::cout << "Waited 5 secs!\n";};
    void intruder(){std::cout << "Cheeky me ;) \n";};
    
    int main()
    {
       std::future<void> f1= std::async(std::launch::deferred, waiter);
       f1.wait_for(std::chrono::seconds(5));
       intruder();
      // f1.get();//returns waiter() immediately;
    }
    Many thanks

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    This works for me:
    Code:
    // g++ -std=c++14 -Wall -W -o threads threads.cpp -lpthread
    #include <iostream>
    #include <chrono>
    #include <thread>
    
    void waiter() {
        using namespace std::chrono_literals;
        std::this_thread::sleep_for(5s);
        std::cout << "Waited 5 secs!\n";
    }
    
    void intruder(){std::cout << "Cheeky me ;) \n";}
     
    int main() {
        std::thread t(waiter);
        intruder();
        t.join();
    }

  3. #3
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    Thanks. A follow-up qs please: here sleep_for was part of the waiter() definition but, instead, if within main() I decide to call a function that does not have a pre-defined sleep_for in it's definition and to launch this function in the background with a similar sleep_for condition how might I achieve that? Thanks again

  4. #4
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Isn't using std::cout not an atomic operation like this? Shouldn't it be accessed via a lock_guard?

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by sean_cantab View Post
    Thanks. A follow-up qs please: here sleep_for was part of the waiter() definition but, instead, if within main() I decide to call a function that does not have a pre-defined sleep_for in it's definition and to launch this function in the background with a similar sleep_for condition how might I achieve that? Thanks again
    You don't need the sleep for a thread to be launched in the background. Sleeps are used in exercises like this as a stand in for long running computations. Without the sleep it's difficult to see what's going on.
    Quote Originally Posted by MutantJohn View Post
    Isn't using std::cout not an atomic operation like this? Shouldn't it be accessed via a lock_guard?
    Pretty sure cout is well defined to use this way. However, yes it might mangle your strings together, so you would need a lock gaurd to prevent that.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  6. #6
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Ah, indeed it is! It looks like it won't result in data races but it will still print incorrectly without programmer synchronization.

  7. #7
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    King Mir: thank you, I came across
    Class thread doesn't have a launch policy. The C++ standard library always tries to start the passed functionality in a new thread. ... Jossutis, Standard Library (2nd ed)
    So now I see what you're trying to say.
    And for completion, circling back to the second program in my OP, is there a way to achieve the same results with std::future and std::async? Thank you

  8. #8
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    std::future has a wait and a get method you can use.

  9. #9
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    std::future.get() would force the waiter() function to start immediately if it was not started yet irrespective of any previous wait_for instructions. So waiter() could return even before the 5s wait is up on the lines of the program in OP. Maybe it can't be done with std::future?

  10. #10
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Does this not do what you want?
    Code:
    #include <iostream>
    #include <chrono>
    #include <thread>
    #include <future>
     
    void waiter()
    {
        using namespace std::chrono_literals;
        std::this_thread::sleep_for(5s);
        std::cout << "Waited 5 secs!\n";
    };
    
    
    void intruder() { std::cout << "Cheeky me ;) \n"; };
     
    int main()
    {
        auto const fut = std::async(std::launch::async, waiter);
        intruder();
        fut.wait();
        return 0;
    }

  11. #11
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    Yes, indeed it does. Just wait() w/o the get(). Many thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 06-06-2016, 02:39 AM
  2. Replies: 11
    Last Post: 12-14-2015, 02:43 PM
  3. Destructor Problem - Seg Fault After Main Returns
    By IdioticCreation in forum C++ Programming
    Replies: 3
    Last Post: 01-05-2011, 05:26 AM
  4. printf waits until main returns to display
    By brightmatter in forum C Programming
    Replies: 30
    Last Post: 01-28-2010, 05:23 PM
  5. main returns int -- compiler returns nonsense
    By Zach L. in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 06-15-2005, 09:53 AM

Tags for this Thread