<>线程-pool机制

来源:互联网 发布:升降设备淘宝推广 编辑:程序博客网 时间:2024/05/16 10:21
 

《 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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <error.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>

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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>

/* 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

原创粉丝点击