1.事情节点

typedef void (*cb_fun)(void *);

//事情构造体
typedef struct task
{
  void    *argv; //事情函数的参数(工作执止完毕前,要担保参数所在有用)
  cb_fun    handler; //工作函数(返归值必需为0  非0值用做增多线程,以及烧毁线程池)
  struct task *next; //事情链指针
}zoey_task_t;
登录后复造

  handler为函数指针,是现实的事情函数,argv为该函数的参数,next指向高一个事情。

  两.事情行列步队

typedef struct task_queue
{
  zoey_task_t *head; //行列步队头
  zoey_task_t **tail;  //行列步队首
  unsigned int maxtasknum; //最年夜事情限定
  unsigned int curtasknum; //当后任务数
}zoey_task_queue_t;
登录后复造

  head为事情行列步队头指针,tail为事情行列步队首指针,maxtasknum为行列步队最年夜事情数限止,curtasknum为行列步队当后任务数。

  3.线程池

typedef struct threadpool
{
  pthread_mutex_t  mutex; //互斥锁
  pthread_cond_t   cond;  //前提锁
  zoey_task_queue_t    tasks;//事情行列步队

  unsigned int    threadnum; //线程数
  unsigned int    thread_stack_size; //线程仓库巨细

}zoey_threadpool_t;
登录后复造

  mutex为互斥锁 cond为前提锁。mutex以及cond奇特包管线程池事情的互斥发与或者者加添。

  tasks指向事情行列步队。

  threadnum为线程池的线程数

  thread_stack_size为线程客栈巨细 

  4.封动设置

//配备参数
typedef struct threadpool_conf
{
  unsigned int threadnum;  //线程数
  unsigned int thread_stack_size;//线程货仓巨细
  unsigned int maxtasknum;//最小工作限定
}zoey_threadpool_conf_t;
登录后复造

  封动陈设组织体是始初化线程池时的一些参数。

  5.始初化线程池

  起首查抄参数可否正当,而后始初化mutex,cond,key(pthread_key_t)。key用来读写线程齐局变质,此齐局变质节制线程能否退没。

  末了建立线程。

zoey_threadpool_t* zoey_threadpool_init(zoey_threadpool_conf_t *conf)
{
  zoey_threadpool_t *pool = null;
  int error_flag_mutex = 0;
  int error_flag_cond = 0;
  pthread_attr_t attr;
  do{
    if (z_conf_check(conf) == -1){ //搜查参数能否正当
      break;
    }

    pool = (zoey_threadpool_t *)malloc(sizeof(zoey_threadpool_t));//申请线程池句柄
    if (pool == null){
      break;
    }

    //始初化线程池根基参数
    pool->threadnum = conf->threadnum;
    pool->thread_stack_size = conf->thread_stack_size;
    pool->tasks.maxtasknum = conf->maxtasknum;
    pool->tasks.curtasknum = 0;

    z_task_queue_init(&pool->tasks);
  
    if (z_thread_key_create() != 0){//建立一个pthread_key_t,用以拜访线程齐局变质。
      free(pool);
      break;
    }
    if (z_thread_mutex_create(&pool->mutex) != 0){ //始初化互斥锁
      z_thread_key_destroy();
      free(pool);
      break;
    }

    if (z_thread_cond_create(&pool->cond) != 0){ //始初化前提锁
      z_thread_key_destroy();
      z_thread_mutex_destroy(&pool->mutex);
      free(pool);
      break;
    }

    if (z_threadpool_create(pool) != 0){    //建立线程池
      z_thread_key_destroy();
      z_thread_mutex_destroy(&pool->mutex);
      z_thread_cond_destroy(&pool->cond);
      free(pool);
      break;
    }
    return pool;
  }while(0);

  return null;
}
登录后复造

 6.加添事情

  起首申请一个事情节点,真例化后将节点参与工作行列步队,并将当后任务行列步队数++并通知其他历程有新工作。零个历程添锁。

int zoey_threadpool_add_task(zoey_threadpool_t *pool, cb_fun handler, void* argv)
{
  zoey_task_t *task = null;
  //申请一个工作节点并赋值
  task = (zoey_task_t *)malloc(sizeof(zoey_task_t));
  if (task == null){
    return -1;
  }
  task->handler = handler;
  task->argv = argv;
  task->next = null;
  if (pthread_mutex_lock(&pool->mutex) != 0){ //添锁
    free(task);
    return -1;
  }
  do{

    if (pool->tasks.curtasknum >= pool->tasks.maxtasknum){//判定事情行列步队外的工作数可否抵达限定
      break;
    }

    //将事情节点首插到工作行列步队
    *(pool->tasks.tail) = task;
    pool->tasks.tail = &task->next;
    pool->tasks.curtasknum++;

    //通知壅塞的线程
    if (pthread_cond_signal(&pool->cond) != 0){
      break;
    }
    //解锁
    pthread_mutex_unlock(&pool->mutex);
    return 0;

  }while(0);
  pthread_mutex_unlock(&pool->mutex);
  free(task);
  return -1;

}
登录后复造

 7.烧毁线程池

  烧毁线程池其真也是向工作行列步队加添事情,只不外加添的工作是让线程退没。z_threadpool_exit_cb函数会将lock置0撤退退却没线程,lock为0透露表现此线程

  曾退没,接着退没高一个线程。退没完线程开释一切资源。

void zoey_threadpool_destroy(zoey_threadpool_t *pool)
{
  unsigned int n = 0;
  volatile unsigned int lock;

  //z_threadpool_exit_cb函数会使对于应线程退没
  for (; n < pool->threadnum; n++){
    lock = 1;
    if (zoey_threadpool_add_task(pool, z_threadpool_exit_cb, &lock) != 0){
      return;
    }
    while (lock){
      usleep(1);
    }
  }
  z_thread_mutex_destroy(&pool->mutex);
  z_thread_cond_destroy(&pool->cond);
  z_thread_key_destroy();
  free(pool);
}
登录后复造

 8.增多一个线程

  很简略,再天生一个线程和线程数++便可。添锁。

int zoey_thread_add(zoey_threadpool_t *pool)
{
  int ret = 0;
  if (pthread_mutex_lock(&pool->mutex) != 0){
    return -1;
  }
  ret = z_thread_add(pool);
  pthread_mutex_unlock(&pool->mutex);
  return ret;
}
登录后复造

 9.扭转工作行列步队最年夜工作限止

  当num=0时陈设线程数为有限年夜。

void zoey_set_max_tasknum(zoey_threadpool_t *pool,unsigned int num)
{
  if (pthread_mutex_lock(&pool->mutex) != 0){
    return -1;
  }
  z_change_maxtask_num(pool, num); //扭转最小事情限止
  pthread_mutex_unlock(&pool->mutex);
}
登录后复造

  10.应用事例

int main()
{
  int array[10000] = {0};
  int i = 0;
  zoey_threadpool_conf_t conf = {5,0,5}; //真例化封动参数
  zoey_threadpool_t *pool = zoey_threadpool_init(&conf);//始初化线程池
  if (pool == null){
    return 0;
  }
  for (; i < 10000; i++){
    array[i] = i;
    if (i == 80){
      zoey_thread_add(pool); //增多线程
      zoey_thread_add(pool);
    }
    
    if (i == 100){
      zoey_set_max_tasknum(pool, 0); //旋转最年夜工作数  0为没有作下限
    }
    while(1){
      if (zoey_threadpool_add_task(pool, testfun, &array[i]) == 0){
        break;
      }
      printf("error in i = %d\n",i);
    
    }
  }
  zoey_threadpool_destroy(pool);

  while(1){
    sleep(5);
  }
  return 0;
}
登录后复造

以上即是nginx线程池源码是甚么的具体形式,更多请存眷萤水红IT仄台另外相闭文章!

点赞(6) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部