Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run a fixed number of threads all the time

I've just started with multithreading. The problem is my code does not start a new thread once one has finished, but rather starts 4 threads once the last 4 finished, so if the tasks take an unequal amount of time, it isn't very efficient and I have thousands of classes to process each time.

Loop()
{
    myClass A,B,C,D;
    std::thread td1(&myClass::run, &A, args[i]);
    std::thread td2(&myClass::run, &B, args[i+1]);
    std::thread td3(&myClass::run, &C, args[i+2]);
    std::thread td4(&myClass::run, &D, args[i+3]);

    td1.join();
    td2.join();
    td3.join();
    td4.join();
}

I found this but it didn't help me at all. I was thinking about using std::promise, std::future or std::packaged_task to monitor if thread already finish but I don't know how to spawn another thread on his place.

In my case I just need X threads running my method with different arguments and their own clean object of myClass. I can't send my calculation work since it needs all the data that's within the class.

like image 551
Zaritor Avatar asked Oct 01 '22 02:10

Zaritor


2 Answers

You could try or create a Thread Pool, still I tried many opensource c++11 ThreadPools and almost all are bugged (deadlock or crash at some point) or have a design flaw that make them useless. You'll find about a dozen Thread Pools just on github.

The simplest solution is to use one (or multiple) WorkQueue, every thread could add some work to the queue or just process the work (if multiple queues the thread will try to get a job from each queue, if all queues are empty it just sleep a little while).

Then you just need a class like that

class myClass: public virtual Runnable{

WorkQueue * q;
std::atomic<bool> running=true; //used to kill the thread

public:

    myClass(WorkQueue * que):q(que){

    }

    /* IMPLEMENTS: Runnable*/
    public virtual void run(){
        int i=0;
        Job * j=nullptr;
        while(running){
            j=q[i]->getNextJob();
            if(j){
                j->run();
                if(j->hasJobsToDispatch())
                    i++;
            }else{
                i++;
            }
            if(i>=queuesNumber)
                i=0;
            q[i]->addSomeJob(j->getJobsToDispatch());
        }
    }

    void stopThread(){
       running!=running;
    }
};
like image 60
CoffeDeveloper Avatar answered Oct 22 '22 18:10

CoffeDeveloper


You should look into either some kind of thread pool, or use std::async (which, depending on your implementation, may use a thread pool underneath).

like image 22
Robert Allan Hennigan Leahy Avatar answered Oct 22 '22 19:10

Robert Allan Hennigan Leahy