linux下線程池代碼

來源:互聯網
上載者:User

//thrmgr.h

#ifndef __THRMGR_H__
#define __THRMGR_H__

#include <sys/time.h>
#include <pthread.h>

typedef struct work_item_tag
{
 struct work_item_tag *next;
 void *data;
 struct timeval time_queued;
} work_item_t;

typedef struct work_queue_tag
{
 work_item_t *head;
 work_item_t *tail;
 int item_count;
} work_queue_t;

typedef enum
{
 POOL_INVALID,
 POOL_VALID,
 POOL_EXIT,
} pool_state_t;

typedef struct threadpool_tag
{
 pthread_mutex_t pool_mutex;
 pthread_cond_t pool_cond;
 pthread_attr_t pool_attr;

 pool_state_t state;
 int thr_max;
 int thr_alive;
 int thr_idle;
 int idle_timeout;

 void (*handler)(void *);

 work_queue_t *queue;
} threadpool_t;

threadpool_t *thrmgr_new(int max_threads, int idle_timeout, void (*handler)(void *));
void thrmgr_destroy(threadpool_t *threadpool);
int  thrmgr_dispatch(threadpool_t *threadpool, void *user_data);

#endif

//thrmgr.c
 #include "thrmgr.h"

#include <stdlib.h>
#include <memory.h>
#include <errno.h>

#define FALSE (0)
#define TRUE (1)

work_queue_t *work_queue_new()
{
 work_queue_t *work_q;

 work_q = (work_queue_t *) malloc(sizeof(work_queue_t));

 work_q->head = work_q->tail = NULL;
 work_q->item_count = 0;
 return work_q;
}

void work_queue_add(work_queue_t *work_q, void *data)
{
 work_item_t *work_item;

 if (!work_q)
 {
  return;
 }
 work_item = (work_item_t *) malloc(sizeof(work_item_t));
 work_item->next = NULL;
 work_item->data = data;
 gettimeofday(&(work_item->time_queued), NULL);

 if (work_q->head == NULL)
 {
  work_q->head = work_q->tail = work_item;
  work_q->item_count = 1;
 }
 else
 {
  work_q->tail->next = work_item;
  work_q->tail = work_item;
  work_q->item_count++;
 }
 return;
}

void *work_queue_pop(work_queue_t *work_q)
{
 work_item_t *work_item;
 void *data;

 if (!work_q || !work_q->head)
 {
  return NULL;
 }

 work_item = work_q->head;
 data = work_item->data;
 work_q->head = work_item->next;
 if (work_q->head == NULL)
 {
  work_q->tail = NULL;
 }

 free(work_item);
 return data;
}

void thrmgr_destroy(threadpool_t *threadpool)
{
 if (!threadpool || (threadpool->state != POOL_VALID))
 {
  return;
 }

 if (pthread_mutex_lock(&threadpool->pool_mutex) != 0)
 {
  //logg("!Mutex lock failed/n");
  exit(-1);
 }
 threadpool->state = POOL_EXIT;

 /* wait for threads to exit */
 if (threadpool->thr_alive > 0)
 {
  if (pthread_cond_broadcast(&(threadpool->pool_cond)) != 0)
  {
   pthread_mutex_unlock(&threadpool->pool_mutex);
   return;
  }
 }

 while (threadpool->thr_alive > 0)
 {
  if (pthread_cond_wait (&threadpool->pool_cond, &threadpool->pool_mutex) != 0)
  {
   pthread_mutex_unlock(&threadpool->pool_mutex);
   return;
  }
 }

 if (pthread_mutex_unlock(&threadpool->pool_mutex) != 0)
 {
  //logg("!Mutex unlock failed/n");
  exit(-1);
 }

 pthread_mutex_destroy(&(threadpool->pool_mutex));
 pthread_cond_destroy(&(threadpool->pool_cond));
 pthread_attr_destroy(&(threadpool->pool_attr));
 free(threadpool);
 return;
}

threadpool_t *thrmgr_new(int max_threads, int idle_timeout, void (*handler)(void *))
{
 threadpool_t *threadpool;

 if (max_threads <= 0)
 {
  return NULL;
 }

 threadpool = (threadpool_t *) malloc(sizeof(threadpool_t));

 threadpool->queue = work_queue_new();
 if (!threadpool->queue)
 {
  free(threadpool);
  return NULL;
 }

 threadpool->thr_max   = max_threads;
 threadpool->thr_alive = 0;
 threadpool->thr_idle  = 0;
 threadpool->idle_timeout = idle_timeout;
 threadpool->handler = handler;

 pthread_mutex_init(&(threadpool->pool_mutex), NULL);
 if (pthread_cond_init(&(threadpool->pool_cond), NULL) != 0)
 {
  free(threadpool);
  return NULL;
 }

 if (pthread_attr_init(&(threadpool->pool_attr)) != 0)
 {
  free(threadpool);
  return NULL;
 }

 if (pthread_attr_setdetachstate(&(threadpool->pool_attr), PTHREAD_CREATE_DETACHED) != 0)
 {
  free(threadpool);
  return NULL;
 }
 threadpool->state = POOL_VALID;

 return threadpool;
}

void *thrmgr_worker(void *arg)
{
 threadpool_t *threadpool = (threadpool_t *) arg;
 void *job_data;
 int retval, must_exit = FALSE;
 struct timespec timeout;

 /* loop looking for work */
 for (;;)
 {
  if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0)
  {
   /* Fatal error */
   //logg("!Fatal: mutex lock failed/n");
   exit(-2);
  }

  timeout.tv_sec = time(NULL) + threadpool->idle_timeout;
  timeout.tv_nsec = 0;
  threadpool->thr_idle++;
  while (((job_data=work_queue_pop(threadpool->queue)) == NULL) && (threadpool->state != POOL_EXIT))
  {
   // Sleep, awaiting wakeup ,
   retval = pthread_cond_timedwait(&(threadpool->pool_cond), &(threadpool->pool_mutex), &timeout);
   if (retval == ETIMEDOUT)
   {
    must_exit = TRUE;
    break;
   }
  }

  threadpool->thr_idle--;
  if (threadpool->state == POOL_EXIT)
  {
   must_exit = TRUE;
  }

  if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0)
  {
   /* Fatal error */
   //logg("!Fatal: mutex unlock failed/n");
   exit(-2);
  }

  if (job_data)
  {
   threadpool->handler(job_data);
  }
  else if (must_exit)
  {
   break;
  }
 }

 if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0)
 {
  /* Fatal error */
  //logg("!Fatal: mutex lock failed/n");
  exit(-2);
 }

 threadpool->thr_alive--;
 if (threadpool->thr_alive == 0)
 {
  /* signal that all threads are finished */
  pthread_cond_broadcast(&threadpool->pool_cond);
 }

 if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0)
 {
  /* Fatal error */
  //logg("!Fatal: mutex unlock failed/n");
  exit(-2);
 }

 return NULL;
}

int thrmgr_dispatch(threadpool_t *threadpool, void *user_data)
{
 pthread_t thr_id;

 if (!threadpool)
 {
  return FALSE;
 }

 /* Lock the threadpool */
 if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0)
 {
  //logg("!Mutex lock failed/n");
  return FALSE;
 }

 if (threadpool->state != POOL_VALID)
 {
  if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0)
  {
   //logg("!Mutex unlock failed/n");
   return FALSE;
  }
  return FALSE;
 }

 work_queue_add(threadpool->queue, user_data);

 //只有當目前沒有線程idle且目前產生的線程數小於最大線程要求時建立新的線程
 if ((threadpool->thr_idle == 0) && (threadpool->thr_alive < threadpool->thr_max))
 {
  /* Start a new thread */
  if (pthread_create(&thr_id, &(threadpool->pool_attr),thrmgr_worker, threadpool) != 0)
  {
   //logg("!pthread_create failed/n");
  }
  else
  {
   threadpool->thr_alive++;
  }
 }

 /*釋放條件訊號,如果有正在等待該訊號的線程,則該線程運行*/
 pthread_cond_signal(&(threadpool->pool_cond));

 if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0)
 {
  //logg("!Mutex unlock failed/n");
  return FALSE;
 }

 return TRUE;
}

/*
使用方法,以一個tcp伺服器為例,簡單列出,

1, thrmgr_new初始話

2, while(1)

{

accept(......);

//構建輸入參數

thrmgr_dispach(...);

}

thrmgr_destory(...);

int main ()
{
 threadpool_t *threadpool = thrmgr_new (5, 0, handle);
 thrmgr_dispatch (threadpool, (void *)5);
 thrmgr_dispatch (threadpool, (void *)7);
 thrmgr_destroy (threadpool);
}
*/

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.