Threadpool how to make a thread pool with queue in C?

1.8k views Asked by At

so i have the following :

a queue "q" that has "jobs" each job is a char ('1'-'6'). i'm trying to create a 5 thread array that will hande this queue, so when one thread finished its tasks it takes another one from the que.

for example the queue is:

q = '3','4','3','3','5','3','4','3','3','5','3','4','3','3','5','3','4','3','3','5'

so i'm having difficuluties to figure this out. any help would be great thank you!

here what i've got so far:

int internal_count = 0;
pthread_t threads[5];
Queue que; // simple char queue (its working)
void createThreads(int numOfThreads) {
    for (int i = 0; i < numOfThreads; i++) {
            pthread_t tid;
            threads[i] = pthread_create(&tid, NULL, start_thread, (void*) que);
            if (threads[i] != 0) { /* error handling */ }
    }
}

i don't know why its not running in this method yet..

void* start_thread(void* arg) {
    char job;
    int fd;
    int x = random_number(10, 100); // its working
    struct timespec tim, tim2;
    pthread_t ptid;
    char *message;
    while (que.size == 0) {

    }
     pthread_mutex_lock(&lock);
    // ADD MUTEX!!!!!!!!!!!!!
    job = que.Dequeue();

    switch(job) {
    case '1':
        // go to sleep
        tim.tv_sec  = 0;
        tim.tv_nsec = x * 1000000L;
        nanosleep(&tim , &tim2);
        internal_count++;
        break;
    case '2':
        // go to sleep
        tim.tv_sec  = 0;
        tim.tv_nsec = x * 1000000L;
        nanosleep(&tim , &tim2);
        internal_count += 2;
        break;
    case '3':
        // go to sleep
        tim.tv_sec  = 0;
        tim.tv_nsec = x * 1000000L;
        nanosleep(&tim , &tim2);
        internal_count += 3;
        break;
    case '4':
        // go to sleep
        tim.tv_sec  = 0;
        tim.tv_nsec = x * 1000000L;
        nanosleep(&tim , &tim2);
        internal_count += 4;
        break;
    case '5':
        // go to sleep
        tim.tv_sec  = 0;
        tim.tv_nsec = x * 1000000L;
        nanosleep(&tim , &tim2);
        internal_count += 5;
        break;
    case '6':
        ptid = pthread_self();
        message = fromIntToString((int) ptid);
        strcat(message, ",");
        strcat(message, fromIntToString(internal_count));
        strcat(message, "\n");
        break;
    default:break;
    }
    pthread_mutex_unlock(&lock);
    return NULL;

}
2

There are 2 answers

3
missimer On

One possible reason, it is hard to tell for sure because you do not have the complete code, is that your main function is returning right after creating all the threads and therefore your process is exiting before the threads get to really do anything. Typical you see pthread_join after creating a bunch of a threads if you want the main thread to just wait for all the threads to finish, again this depends on your application. A quick way to check if this is your problem (and this is not a good solution just a way to check) is to put a while(1); (note the semicolon) at the end of your main so it does not exit and just spins waiting so your other threads get a chance to run.

Also you typically just have the mutex locked when you dequeue the job element, not while you process it. This way another thread can remove something from the queue while the threads are processing the job. This is of course unless processing the job requires access to some other global data but you would probably want a different lock around that global data then. This probably doesn't relate to why you aren't seeing the threads run though.

0
Akin Ocal On

You haven`t posted full code , but quick notes based on existing question :

  • Check if you are correctly initializing your pthread mutex. Look at pthread_mutex_init or PTHREAD_MUTEX_INITIALIZER

  • You are using lock object only for queue operation. However you will need a critical section for size function of queue as well unless you are managing it atomically.

  • Regarding why your thread function is not running , you have to dig into more and see whether your threads did not start or they just can`t go forward. You can easily do this by setting up breakpoints inside your thread function. Also in GDB you can use "info threads" to see created threads.

  • Rather than using a while loop to check against if a task submitted to the queue, I would strongly suggest you using condition variables as they are built-in synchronization primitives for what you are doing.

The article is in C++ and uses C++11 threading library but gives nice information about both condition variables and how to implement a thread safe queue as that is what you need to know for implementing a thread pool :

Implementing a thread safe queue using condition variables