4

I am new to threading in C++11 and I am wondering how to manage worker threads (using the standard library) to perform some task and then die off. I have a pool of threads vector<thread *> thread_pool that maintains a list of active threads.

Let's say I launch a new thread and add it to the pool using thread_pool.push_back(new thread(worker_task)), where worker_task is defined as follows:

void worker_task()
{
    this_thread::sleep_for(chrono::milliseconds(1000));
    cout << "Hello, world!\n"
}

Once the worker thread has terminated, what is the best way to reliably remove the thread from the pool? The main thread needs to run continuously and cannot block on a join call. I am more confused about the general structure of the code than the intricacies of synchronization.

Edit: It looks like I misused the concept of a pool in my code. All I meant was that I have a list of threads that are currently running.

Chirag
  • 131
  • 1
  • 1
  • 4
  • 1
    What's the purpose of a _thread pool_ if each thread only executes one task? – nosid Jul 01 '14 at 18:24
  • 1
    ftp://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html read this before you think about constructing your thread pool architecture. – Alexander Oh Jul 01 '14 at 18:35
  • That's not what "pool" means... – Kerrek SB Jul 01 '14 at 18:37
  • @nosid I simplified the situation for the sake of the question. The threads I am creating will not be as short as the worker_task function I showed above, and I need to be able to display what all the threads are working on at any given time. The thread_pool actually won't contain a list of thread objects, but will contain metadata associated with each thread. – Chirag Jul 01 '14 at 18:37
  • @nosid OP never wrote that, it is a "pool of thread" not a "thread pool", OP also stated "to perform some task and then die off" which is a statement that suggests that OP is not interested in a "thread pool" approach anyway. – user2485710 Jul 01 '14 at 18:44
  • 1
    Related: [How to check if a std::thread is still running?](http://stackoverflow.com/q/9094422/873025). – Felix Glas Jul 01 '14 at 20:08

1 Answers1

3

You can use std::thread::detach to "separate the thread of execution from the thread object, allowing execution to continue independently. Any allocated resources will be freed once the thread exits."

If each thread should make its state visible, you can move this functionality into the thread function.

std::mutex mutex;
using strings = std::list<std::string>;
strings info;

strings::iterator insert(std::string value) {
    std::unique_lock<std::mutex> lock{mutex};
    return info.insert(info.end(), std::move(value));
}

auto erase(strings::iterator p) {
    std::unique_lock<std::mutex> lock{mutex};
    info.erase(p);
}

template <typename F>
void async(F f) {
    std::thread{[f] {
        auto p = insert("...");
        try {
            f();
        } catch (...) {
            erase(p);
            throw;
        }
        erase(p);
    }}.detach();
}
nosid
  • 48,932
  • 13
  • 112
  • 139
  • Thanks! I didn't know about the detach function so I'll look into that. One question about your code though, how come the erase is inside a catch? Is f expected to throw an exception when it is completed? – Chirag Jul 01 '14 at 20:02
  • 1
    @Chirag: `erase` should be invoked regardless how the function terminates. However, I missed the case of successful termination. It would be better to use RAII instead. – nosid Jul 01 '14 at 20:05