Simple implementation of a thread pool

Source: Internet
Author: User

Thread Pool implementation: used to execute a large number of relatively short-lived tasks. When a task increases, the number of threads in the thread pool can be dynamically increased until a threshold value is reached. When the task is completed, the threads in the thread pool can be dynamically destroyed.
The implementation of this thread pool is essentially an application of the producer and consumption model. The producer thread adds a task to the task queue. Once a task arrives in the queue, the producer will wake up to execute the task if there is a waiting thread. If the number of threads does not reach the threshold, create a new thread to execute the task.

Contion. h # ifndef _ CONDITION_H _
# Define _ CONDITION_H _


# Include


Typedef struct condition
{
Pthread_mutex_t pmutex;
Pthread_cond_t pcond;
} Condition_t;


Int condition_init (condition_t * cond );
Int condition_lock (condition_t * cond );
Int condition_unlock (condition_t * cond );
Int condition_wait (condition_t * cond );
Int condition_timedwait (condition_t * cond, const struct timespec * abstime );
Int condition_signal (condition_t * cond );
Int condition_broadcast (condition_t * cond );
Int condition_destroy (condition_t * cond );


# Endif/* _ CONDITION_H _*/

Condition. c # include "condition. h"


Int condition_init (condition_t * cond)
{
Int status;
If (status = pthread_mutex_init (& cond-> pmutex, NULL )))
Return status;


If (status = pthread_cond_init (& cond-> pcond, NULL )))
Return status;


Return 0;
}


Int condition_lock (condition_t * cond)
{
Return pthread_mutex_lock (& cond-> pmutex );
}


Int condition_unlock (condition_t * cond)
{
Return pthread_mutex_unlock (& cond-> pmutex );
}


Int condition_wait (condition_t * cond)
{
Return pthread_cond_wait (& cond-> pcond, & cond-> pmutex );
}


Int condition_timedwait (condition_t * cond, const struct timespec * abstime)
{
Return pthread_cond_timedwait (& cond-> pcond, & cond-> pmutex, abstime );
}




Int condition_signal (condition_t * cond)
{
Return pthread_cond_signal (& cond-> pcond );
}


Int condition_broadcast (condition_t * cond)
{
Return pthread_cond_broadcast (& cond-> pcond );
}


Int condition_destroy (condition_t * cond)
{
Int status;
If (status = pthread_mutex_destroy (& cond-> pmutex )))
Return status;


If (status = pthread_cond_destroy (& cond-> pcond )))
Return status;


Return 0;
}


Threadpool. h # ifndef _ THREAD_POOL_H _
# Define _ THREAD_POOL_H _


# Include "condition. h"


// Task struct, which puts tasks into the queue for execution by threads in the thread pool
Typedef struct task
{
Void * (* run) (void * arg); // task callback function
Void * arg; // callback function parameter
Struct task * next;
} Task_t;


// Thread pool struct
Typedef struct threadpool
{
Condition_t ready; // notification that the task is ready or the thread pool is destroyed
Task_t * first; // task queue header pointer
Task_t * last; // task queue tail pointer
Int counter; // The number of threads in the thread pool.
Int idle; // Number of threads in the thread pool that are currently waiting for tasks
Int max_threads; // maximum number of threads allowed in the thread pool
Int quit; // set this parameter to 1 when the thread pool is destroyed.
} Threadpool_t;


// Initialize the thread pool
Void threadpool_init (threadpool_t * pool, int threads );
// Add a task to the thread pool
Void threadpool_add_task (threadpool_t * pool, void * (* run) (void * arg), void * arg );
// Destroy the thread pool
Void threadpool_destroy (threadpool_t * pool );


# Endif/* _ THREAD_POOL_H _*/

Threadpool. c # include "threadpool. h"
# Include
# Include
# Include
# Include
# Include


Void * thread_routine (void * arg)
{
Struct timespec abstime;
Int timeout;
Printf ("thread 0x % x is starting \ n", (int) pthread_self ());
Threadpool_t * pool = (threadpool_t *) arg;
While (1)
{
Timeout = 0;
Condition_lock (& pool-> ready );
Pool-> idle ++;
// Wait for the queue to have a task arrival or thread pool destruction notification
While (pool-> first = NULL &&! Pool-> quit)
{
Printf ("thread 0x % x is waiting \ n", (int) pthread_self ());
// Condition_wait (& pool-> ready );
Clock_gettime (CLOCK_REALTIME, & abstime );
Abstime. TV _sec + = 2;
Int status = condition_timedwait (& pool-> ready, & abstime );
If (status = ETIMEDOUT)
{
Printf ("thread 0x % x is wait timed out \ n", (int) pthread_self ());
Timeout = 1;
Break;
}
}


// Wait for the condition to be in the working state
Pool-> idle --;


// Wait for the task
If (pool-> first! = NULL)
{
// Retrieve the task from the queue Header
Task_t * t = pool-> first;
Pool-> first = t-> next;
// It takes some time to execute the task. Therefore, you must unlock the task so that the producer process can
// Can add tasks to the queue, and other consumer threads can enter the waiting task
Condition_unlock (& pool-> ready );
T-> run (t-> arg );
Free (t );
Condition_lock (& pool-> ready );
}
// If the thread pool is waiting for a notification of destruction and all tasks have been completed
If (pool-> quit & pool-> first = NULL)
{
Pool-> counter --;
If (pool-> counter = 0)
Condition_signal (& pool-> ready );


Condition_unlock (& pool-> ready );
// Remember to unlock before jumping out of the loop
Break;
}


If (timeout & pool-> first = NULL)
{
Pool-> counter --;
Condition_unlock (& pool-> ready );
// Remember to unlock before jumping out of the loop
Break;
}
Condition_unlock (& pool-> ready );
}


Printf ("thread 0x % x is exting \ n", (int) pthread_self ());
Return NULL;


}


// Initialize the thread pool
Void threadpool_init (threadpool_t * pool, int threads)
{
// Initialize fields in the thread pool
Condition_init (& pool-> ready );
Pool-> first = NULL;
Pool-> last = NULL;
Pool-> counter = 0;
Pool-> idle = 0;
Pool-> max_threads = threads;
Pool-> quit = 0;
}


// Add a task to the thread pool
Void threadpool_add_task (threadpool_t * pool, void * (* run) (void * arg), void * arg)
{
// Generate a new task
Task_t * newtask = (task_t *) malloc (sizeof (task_t ));
Newtask-> run = run;
Newtask-> arg = arg;
Newtask-> next = NULL;


Condition_lock (& pool-> ready );
// Add the task to the queue
If (pool-> first = NULL)
Pool-> first = newtask;
Else
Pool-> last-> next = newtask;
Pool-> last = newtask;


// If there is a waiting thread, wake up one of them
If (pool-> idle> 0)
Condition_signal (& pool-> ready );
Else if (pool-> counter <pool-> max_threads)
{
// If no waiting thread exists and the number of threads cannot exceed the maximum, a new thread is created.
Pthread_t tid;
Pthread_create (& tid, NULL, thread_routine, pool );
Pool-> counter ++;
}
Condition_unlock (& pool-> ready );
}


// Destroy the thread pool
Void threadpool_destroy (threadpool_t * pool)
{
If (pool-> quit)
{
Return;
}
Condition_lock (& pool-> ready );
Pool-> quit = 1;
If (pool-> counter> 0)
{
If (pool-> idle> 0)
Condition_broadcast (& pool-> ready );


// The thread in the task execution status will not receive a broadcast
// The thread pool needs to wait until all threads in the execution task state exit


While (pool-> counter> 0)
Condition_wait (& pool-> ready );
}
Condition_unlock (& pool-> ready );
Condition_destroy (& pool-> ready );




}

Main. c # include "threadpool. h"
# Include
# Include
# Include


Void * mytask (void * arg)
{
Printf ("thread 0x % x is working on task % d \ n", (int) pthread_self (), * (int *) arg );
Sleep (1 );
Free (arg );
Return NULL;
}


Int main (void)
{
Threadpool_t pool;
Threadpool_init (& pool, 3 );


Int I;
For (I = 0; I <10; I ++)
{
Int * arg = (int *) malloc (sizeof (int ));
* Arg = I;
Threadpool_add_task (& pool, mytask, arg );
}


// Sleep (15 );
Threadpool_destroy (& pool );
Return 0;
}

Makefile:. PHONY: clean
CC = gcc
CFLAGS =-Wall-g
ALL = main
All: $ (ALL)
OBJS = threadpool. o main. o condition. o
. C. o:
$ (CC) $ (CFLAGS)-c $ <


Main: $ (OBJS)
$ (CC) $ (CFLAGS) $ ^-o $ @-lpthread-lrt


Clean:
Rm-f $ (ALL) *. o

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.