silverAndroid
silverAndroid

Reputation: 1050

Making a queue of threads in C++

I'm trying to run threads one after the other. I know I could do them serially but the whole point is so the commands don't block the UI.

However, in the implementation I came up with, I can't use std::thread because I can't pass threads as a parameter.

Is there another way I can do this?


This is my current implementation:

#include <mutex>
#include <thread>
#include <queue>

class ThreadQueue {
    std::queue <std::thread> threads;
    std::mutex mutex_add;
    std::mutex mutex_remove;

public:
   ThreadQueue() {}

    ~ThreadQueue() {}

    void add(std::thread thread) {
        mutex_add.lock();
        threads.push(thread);
        mutex_add.unlock();
    }

    std::thread remove() {
        mutex_remove.lock();
        std::thread thread = threads.front;
        threads.pop();
        thread.join();
        mutex_remove.unlock();
    }
};

Upvotes: 0

Views: 5243

Answers (2)

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

I know I could do them serially but the whole point is so the commands don't block the UI.


Is there another way I can do this?

As it was already mentioned std::thread is a movable class type and you could use std::move() to transfer them in the queue.


But I don't think it's a good design to use a queue of std::thread instances.

Let's suppose you're placing a thread instance to that queue that utilizes a thread function, it will be started immediately. So then, what's the role of the queue here?
Should the thread pop itself from the queue as soon it was started? Who's going to join() it then?


As @alexeibs suggests you should have one thread, that executes UI background tasks (e.g. std::function objects) that are read from the queue.

You could even have such task queue being shared by multiple threads (aka thread pool), and maximize your available CPU cores' utilization (ideally you shouldn't have more active threads than CPU cores available).

The synchronization (mutexes, condition variables for notifying etc.) should be applied to the queue itself then.

Upvotes: 4

Loki Astari
Loki Astari

Reputation: 264401

You can move threads:

So you can simply fix your code like this.

void add(std::thread&& thread) {
          //        ^^   
        mutex_add.lock();
        threads.push(std::move(thread));
          //         ^^^^^^^^^
        mutex_add.unlock();
    }

But saying that there are other ways to solve this that may be better.

Rather than having a queue of threads that can be added and removed. Have an queue of jobs that are executed by a thread(s) owned by the object. Or you can simply use std::async() to start jobs in the background.

Upvotes: 2

Related Questions