/** * This function obtains a queued task from the pool and returns it. * If no such task is available the operation blocks. * * @param pool The thread pool structure. * @return A task or NULL on error (or if thread pool should shut down). */ static struct threadpool_task* threadpool_task_get_task(struct threadpool *pool) { struct threadpool_task* task; /* Obtain a task */ if (pthread_mutex_lock(&(pool->mutex))) { perror("pthread_mutex_lock: "); return NULL; } while (threadpool_queue_is_empty(&(pool->tasks_queue))) { if (pool->stop_flag) { if (pthread_cond_broadcast(&(pool->cond))) { perror("pthread_cond_broadcast: "); } if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); return NULL; } return NULL; } /* Block until a new task arrives. */ if (pthread_cond_wait(&(pool->cond),&(pool->mutex))) { perror("pthread_cond_wait: "); if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); } return NULL; } } if ((task = (struct threadpool_task*)threadpool_queue_dequeue(&(pool->tasks_queue))) == NULL) { /* Since task is NULL returning task will return NULL as required. */ REPORT_ERROR("Failed to obtain a task from the jobs queue."); } if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); return NULL; } return task; }
static struct threadpool_task* threadpool_task_get_task(struct threadpool *pool) { struct threadpool_task* task; if (pthread_mutex_lock(&(pool->mutex))) { perror("pthread_mutex_lock: "); return NULL; } while (threadpool_queue_is_empty(&(pool->tasks_queue))) { if (pool->stop_flag) { if (pthread_cond_broadcast(&(pool->cond))) { perror("pthread_cond_broadcast: "); } if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); return NULL; } return NULL; } if (pthread_cond_wait(&(pool->cond),&(pool->mutex))) { perror("pthread_cond_wait: "); if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); } return NULL; } } if ((task = (struct threadpool_task*)threadpool_queue_dequeue(&(pool->tasks_queue))) == NULL) { DEMO_THREAD_Print("Failed to obtain a task from the jobs queue."); } if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); return NULL; } return task; }
int threadpool_add_task(struct threadpool *pool, void (*routine)(void*), void *data, int blocking) { struct threadpool_task *task; if (pool == NULL) { REPORT_ERROR("The threadpool received as argument is NULL."); return -1; } if (pthread_mutex_lock(&(pool->free_tasks_mutex))) { perror("pthread_mutex_lock: "); return -1; } /* Check if the free task queue is empty. */ while (threadpool_queue_is_empty(&(pool->free_tasks_queue))) { if (!blocking) { /* Return immediately if the command is non blocking. */ if (pthread_mutex_unlock(&(pool->free_tasks_mutex))) { perror("pthread_mutex_unlock: "); return -1; } return -2; } /* blocking is set to 1, wait until free_tasks queue has a task to obtain. */ if (pthread_cond_wait(&(pool->free_tasks_cond),&(pool->free_tasks_mutex))) { perror("pthread_cond_wait: "); if (pthread_mutex_unlock(&(pool->free_tasks_mutex))) { perror("pthread_mutex_unlock: "); } return -1; } } /* Obtain an empty task. */ if ((task = (struct threadpool_task*)threadpool_queue_dequeue(&(pool->free_tasks_queue))) == NULL) { REPORT_ERROR("Failed to obtain an empty task from the free tasks queue."); if (pthread_mutex_unlock(&(pool->free_tasks_mutex))) { perror("pthread_mutex_unlock: "); } return -1; } if (pthread_mutex_unlock(&(pool->free_tasks_mutex))) { perror("pthread_mutex_unlock: "); return -1; } task->data = data; task->routine_cb = routine; /* Add the task, to the tasks queue. */ if (pthread_mutex_lock(&(pool->mutex))) { perror("pthread_mutex_lock: "); return -1; } if (threadpool_queue_enqueue(&(pool->tasks_queue),task)) { REPORT_ERROR("Failed to add a new task to the tasks queue."); if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); } return -1; } if (threadpool_queue_getsize(&(pool->tasks_queue)) == 1) { /* Notify all worker threads that there are new jobs. */ if (pthread_cond_broadcast(&(pool->cond))) { perror("pthread_cond_broadcast: "); if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); } return -1; } } if (pthread_mutex_unlock(&(pool->mutex))) { perror("pthread_mutex_unlock: "); return -1; } return 0; }