《 makefile》
CC = gcc
CFLAGS = -O0 -Wall -g
threadpool:threadpool.c
$(CC) $(CFLAGS) -o $@ $^ -lpthread
clean:
$(RM) .*.sw? threadpool *.o
.PHONY:clean
*************************************
《头文件》
#ifndef __IPC__H__
#define __IPC__H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct flock lock;
#pragma pack(4)
#define BUFFER_SIZE 1024
#define Error(info) \
do{ \
fprintf(stderr,"%s:%s\n",info,strerror(errno)); \
exit(EXIT_FAILURE); \
}while(0)
typedef struct msgbuf
{
long mtype; /* message type, must be > 0 */
char ptext[1024]; /* message data */
}msgbuf;
#endif
*******************************************
《pool代码》
#include
#include
#include
#include
#include
#include
/* the pool contains some of
** these structures
*/
typedef struct worker
{
void *(*process) (void *arg);
void *arg; // arguments for process
struct worker *next;
}CThread_worker;
// the pool
typedef struct
{
pthread_mutex_t queue_lock;
pthread_cond_t queue_ready;
// all waiting tasks
CThread_worker *queue_head;
int shutdown;
pthread_t *threadid;
// max active taks
int max_thread_num;
// current waitting tasks
int cur_queue_size;
}CThread_pool;
int pool_add_worker (void *(*process) (void *arg), void *arg);
void *thread_routine (void *arg);
static CThread_pool *pool = NULL;
void pool_init (int max_thread_num)
{
pool = (CThread_pool *) malloc (sizeof (CThread_pool));
pthread_mutex_init (&(pool->queue_lock), NULL);
pthread_cond_init (&(pool->queue_ready), NULL);
pool->queue_head = NULL;
pool->max_thread_num = max_thread_num;
pool->cur_queue_size = 0;
pool->shutdown = 0;
pool->threadid =
(pthread_t *) malloc (max_thread_num * sizeof (pthread_t));
int i = 0;
for(i = 0; i < max_thread_num; i++)
{
pthread_create (&(pool->threadid[i]), NULL,
thread_routine ,NULL);
printf("id=%#x\n\n", (int)pool->threadid[i]);
}
}
// add task into the pool!
int pool_add_worker (void *(*process) (void *arg), void *arg)
{
// instruct a new task
CThread_worker *newworker =
(CThread_worker *) malloc (sizeof (CThread_worker));
newworker->process = process; // the func which task executes
newworker->arg = arg; // arguments
newworker->next = NULL; // the last element in the queue
// lock the queue, and then add the new task
// into the queue.
pthread_mutex_lock (&(pool->queue_lock));
CThread_worker *member = pool->queue_head;
// queue isnot EMPTY
if (member != NULL)
{
while (member->next != NULL)
member = member->next;
member->next = newworker;
}
// queue is EMPTY
else
{
pool->queue_head = newworker;
}
//assert (pool->queue_head != NULL);
pool->cur_queue_size++; // waiting tasks increase
printf("pool_add_ worker pool->cur_queue_size=%d\n",
pool->cur_queue_size);
pthread_mutex_unlock (&(pool->queue_lock));
// wake up waiting task
pthread_cond_signal(&(pool->queue_ready));
sleep(3);
return 0;
}
// tasks waiting in the queue will be discarded
// but will wait for the tasks which are still
// running in the pool
int pool_destroy(void)
{
// make sure it wont be
// destroy twice
if (pool->shutdown)
return -1;
pool->shutdown = 1; // set the flag
// wake up all of the tasks
pthread_cond_broadcast (&(pool->queue_ready));
// wait for all of the task exit
int i;
for (i = 0; i < pool->max_thread_num; i++)
pthread_join (pool->threadid[i], NULL);
free (pool->threadid);
// destroy the queue
CThread_worker *head = NULL;
while (pool->queue_head != NULL)
{
head = pool->queue_head;
pool->queue_head = pool->queue_head->next;
free (head);
}
// destroy the mutex and cond
pthread_mutex_destroy(&(pool->queue_lock));
pthread_cond_destroy(&(pool->queue_ready));
free (pool);
pool=NULL;
return 0;
}
void * thread_routine (void *arg)
{
printf ("%d starting thread %#x\n", __LINE__, (int)pthread_self ());
while (1)
{
pthread_mutex_lock (&(pool->queue_lock));
// routine will waiting for a task to run!
while(pool->cur_queue_size == 0 && !pool->shutdown)
{
printf ("thread %#x is waiting\n", (int)pthread_self ());
printf("pool->shutdown=%d\n",pool->shutdown);
pthread_cond_wait (&(pool->queue_ready),
&(pool->queue_lock));
}
// the pool is shutting down
if (pool->shutdown == 1)
{
// must unlock before any break
// contiune, return
pthread_mutex_unlock (&(pool->queue_lock));
printf ("thread %#x will exit\n", (int)pthread_self ());
pthread_exit (NULL);
}
printf ("thread %#x is starting to work\n",
(int)pthread_self ());
//assert (pool->cur_queue_size != 0);
//assert (pool->queue_head != NULL);
printf("pool->cur_queue_size=%d\n",pool->cur_queue_size);
pool->cur_queue_size--;
CThread_worker *worker = pool->queue_head;
pool->queue_head = worker->next;
pthread_mutex_unlock (&(pool->queue_lock));
// run the process
(*(worker->process))(worker->arg);
free (worker);
worker = NULL;
}
// should never be exectuted
pthread_exit(NULL);
}
void *myprocess(void *arg)
{
printf ("running in myprocess, threadid: %#x,"
"working on task %d\n\n", (int)pthread_self(), *(int *)arg);
// sleep 1 sec, make the task lasting longer
sleep (1);
return NULL;
}
int main (int argc, char **argv)
{
pool_init(3); // 3 threads active most
// throw 5 tasks into the pool
int *workingnum = (int *)malloc(sizeof(int) * 5);
int i;
for(i = 0; i < 5; i++)
{
workingnum[i] = i+70;
pool_add_worker(myprocess, &workingnum[i]);
}
// waiting for all of the tasks
sleep(8);
// destroy the pool
pool_destroy ();
free (workingnum);
return 0;
}
执行:
lsb@ubuntu:~/gx/wangluo$ ./threadpool
j结果:
lsb@ubuntu:~/gx/wangluo$ ./threadpool
id=0xb770ab70
id=0xb6f09b70
id=0xb6708b70
pool_add_ worker pool->cur_queue_size=1
162 starting thread 0xb770ab70
thread 0xb770ab70 is starting to work
pool->cur_queue_size=1
running in myprocess, threadid: 0xb770ab70,working on task 70
162 starting thread 0xb6f09b70
thread 0xb6f09b70 is waiting
pool->shutdown=0
162 starting thread 0xb6708b70
thread 0xb6708b70 is waiting
pool->shutdown=0
thread 0xb770ab70 is waiting
pool->shutdown=0
pool_add_ worker pool->cur_queue_size=1
thread 0xb6f09b70 is starting to work
pool->cur_queue_size=1
running in myprocess, threadid: 0xb6f09b70,working on task 71
thread 0xb6f09b70 is waiting
pool->shutdown=0
pool_add_ worker pool->cur_queue_size=1
thread 0xb6708b70 is starting to work
pool->cur_queue_size=1
running in myprocess, threadid: 0xb6708b70,working on task 72
thread 0xb6708b70 is waiting
pool->shutdown=0