Nginx Line Cheng Code Analysis _nginx

Source: Internet
Author: User
Tags data structures mutex

The weekend read the Nginx thread pool part of the code, conveniently copied, written in its own version. There are differences in the implementation of some places, but the basic structure of all excerpts.

Share it here. If you read my version, you'll see that you understand the nginx thread pool.

This article only lists the key data structures and APIs, and focuses on understanding the nginx thread pool design ideas. The complete code is in the final link.

1. Task nodes

typedef void (*cb_fun) (void *);

Task structure
typedef struct task
{
  void    *argv//Task function parameters (to ensure that the parameter address is valid before the task execution is completed)
  cb_fun    handler;// Task function (The return value must be 0  non 0 value as an addition thread, and destroy the thread pool)
  struct task *next;//tasks chain pointer
}zoey_task_t;

Handler is the function pointer, is the actual task function, argv is the parameter of the function, and next points to the next task.

2. Task Queue

typedef struct TASK_QUEUE
{
  zoey_task_t *head;//Queue head
  zoey_task_t **tail;  Queue tail
  unsigned int maxtasknum;//MAX task limit
  unsigned int curtasknum;//Current number of tasks
}zoey_task_queue_t;

Head is the task queue header pointer, tail is the task queue tail pointer, maxtasknum limit the maximum number of queues for the queue, Curtasknum is the number of current tasks for the queue.

3. Thread pool

typedef struct ThreadPool
{
  pthread_mutex_t  mutex;//Mutex lock
  pthread_cond_t   cond;  Conditional lock
  zoey_task_queue_t    tasks;//task Queue

  unsigned int    threadnum;//number of threads
  unsigned int    thread _stack_size; Thread stack size

}zoey_threadpool_t;

The mutex cond the mutex as a conditional lock. Mutexes and cond together ensure that the thread pool task is mutually exclusive or added.

Tasks point to task queues.

Number of threads threadnum to the thread pool

Thread_stack_size for thread stack size

4. Start configuration

Configuration parameters
typedef struct THREADPOOL_CONF
{
  unsigned int threadnum;  Thread Count
  unsigned int thread_stack_size;//thread stack size
  unsigned int maxtasknum;//max task limit
}zoey_threadpool_ conf_t;

The startup configuration structure is some of the parameters when the thread pool is initialized.

5. Initializing the thread pool

First check that the arguments are legitimate, and then initialize Mutex,cond,key (pthread_key_t). Key is used to read and write the thread global variable, which controls whether the thread exits.

Finally, the thread is created.

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) {//Check whether the parameter is legal break;
    Pool = (zoey_threadpool_t *) malloc (sizeof (zoey_threadpool_t));//request thread pool handle if (pool = = NULL) {break;
    }//Initialize thread pool basic parameters 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) {//Create a pthread_key_t to access the thread global variable.
      Free (pool);
    Break
      } if (Z_thread_mutex_create (&pool->mutex)!= 0) {//Initialize mutual-exclusion lock Z_thread_key_destroy ();
      Free (pool);
    Break
      } if (Z_thread_cond_create (&pool->cond)!= 0) {//Initialization condition lock Z_thread_key_destroy (); Z_thread_mutex_destroy (&Amp;pool->mutex);
      Free (pool);
    Break
      } if (Z_threadpool_create (pool)!= 0) {//Create thread pool 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. Add a task

First you request a task node, instantiate it, add the node to the task queue, and add the current task queue number + + and notify other processes of a new task. Lock the whole process.

int Zoey_threadpool_add_task (zoey_threadpool_t *pool, Cb_fun handler, void* argv)
{zoey_task_t *task
  = null;< c3/>//apply for a task node and assign 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) {//Lock free
    (Task);
    return-1;
  }
  do{

    if (pool->tasks.curtasknum >= pool->tasks.maxtasknum) {//Determine whether the number of tasks in the work queue reaches the limit break
      ;
    }

    Insert the end of the task node into the task queue
    * (pool->tasks.tail) = task;
    Pool->tasks.tail = &task->next;
    pool->tasks.curtasknum++;

    Notifies the blocked thread
    if (pthread_cond_signal (&pool->cond)!= 0) {break
      ;
    }
    Unlock
    pthread_mutex_unlock (&pool->mutex);
    return 0;

  } while (0);
  Pthread_mutex_unlock (&pool->mutex);
  Free (Task);
  return-1;

}

7. Destroying the thread pool

Destroying the thread pool is actually adding tasks to the task queue, except that the task is to have the thread quit. The Z_THREADPOOL_EXIT_CB function will lock a 0 back thread and lock is 0 to indicate that the thread

Has exited, then exits the next thread. Exit the thread and release all resources.

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

  The Z_THREADPOOL_EXIT_CB function causes the corresponding thread to exit 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. Add a thread

It's simple, then generate a thread and the number of threads + +. Lock

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. Change Task Queue maximum task limit

Set the number of threads to infinity when 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); Change Maximum task limit
  pthread_mutex_unlock (&pool->mutex);
}

10. Using the example

int main ()
{
  int array[10000] = {0};
  int i = 0;
  zoey_threadpool_conf_t conf = {5,0,5}; Instantiate startup parameter
  zoey_threadpool_t *pool = Zoey_threadpool_init (&conf);//Initialize thread pool
  if (pool = NULL) {return
    0;
  }
  for (; i < 10000; i++) {
    array[i] = i;
    if (i = =) {
      zoey_thread_add (pool);//Add thread
      zoey_thread_add (pool);
    }
    
    if (i = =) {
      zoey_set_max_tasknum (pool, 0);//Change the maximum number of tasks  0 is not upper limit
    } 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;
}

11. Source Code

Https://github.com/unlikewashface/zoey_threadpool.git

Thread pooling can be more useful, such as putting a connection to a line Cheng Chili. Nginx's asynchronous plus Lua coprocessor is a very good combination, and now that the thread pool is available, the thread pool Ga will be another choice. All in all, it is very good news to make Nginx development very simple if it is guaranteed to be performance.

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.