Implementing queues on Linux platforms

Source: Internet
Author: User
Tags int size mutex

Reprint: http://my.oschina.net/sundq/blog/203600

There are two kinds of event notification methods on Linux, one is thread condition variable, one is implementing event notification with EVENTFD, and the method of implementing asynchronous queue by using these two methods is described below.

Introduction to Thread condition variable correlation function
    • Pthread_cond_init: Initializes a thread condition variable.
    • Pthread_cond_wait: Wait for the condition to trigger.
    • Pthread_cond_signal: Notifies a thread that a thread condition has occurred.
    • Pthread_cond_timedwait: Wait for the condition to trigger, you can set the time-out.
    • PTHREAD_COND_RELTIMEDWAIT_NP: The same as pthread_cond_timedwait use, the difference is that the relative time interval is used instead of the absolute time interval.
    • Pthread_cond_broadcast: Notifies all waiting threads that a thread condition has occurred.
    • Pthread_cond_destroy: Destroys the condition variable.
Wake-up loss issues

If the thread does not hold a mutex associated with the condition, calling pthread_cond_signal () or pthread_cond_broadcast () results in a wake-up loss error. A wake-up loss issue occurs when all of the following conditions are true:

    • One thread calls Pthread_cond_signal () or Pthread_cond_broadcast ()
    • Another thread has tested the condition, but has not yet called pthread_cond_wait ()
    • There are no threads waiting

The signal does not work, so it will be lost, and this problem only occurs if you modify the condition under test but do not hold the mutex associated with it. You can call Pthread_cond_signal () and Pthread_cond_broadcast (), regardless of whether the function holds the associated mutex, as long as you modify the conditions under test only while holding the associated mutex lock.

How to use thread condition variables
Get_resources (int amount)    {        pthread_mutex_lock (&rsrc_lock);        While (Resources < amount)    {            pthread_cond_wait (&rsrc_add, &rsrc_lock);   }      Resources-= amount;   Pthread_mutex_unlock (&rsrc_lock); 

}

add_resources (int amount)
{

Pthread_mutex_lock (&rsrc_lock);   Resources + = amount;   Pthread_cond_broadcast (&rsrc_add);   Pthread_mutex_unlock (&rsrc_lock);}
Eventfd

int eventfd(unsigned int initval, int flags);

eventfdLinux provides the kernel state of the event wait/notification mechanism, the kernel maintains a 8-byte integer number, the integer number is initval initialized, the flags parameters can be from the following value bits or:

    • Efd_cloexec: Sets the flag for this descriptor O_CLOEXEC .
    • Efd_nonblock: The setting descriptor is non-blocking mode.
    • Efd_semaphore: The set descriptor is Semaphore operation mode, in which the read mode will reduce the number of integers by 1 and return the value 1.

When the kernel maintains a 8-byte integer number of 0 o'clock, the read operation is blocked and an error is returned if the FD is set to non-blocking mode EAGAIN .

Simple wake-up queue

Below we implement a simple ring queue:

#Define Default_size 1024typedefstructqueue{int header;int tail;int size;int capcity;void **_buf;}queue_t;queue_t *queue_create (int size) {queue_t *q =mallocsizeof (queue_t));if (q! =NULL) {if (Size >0) {Q->_buf =malloc (size); q->capcity = size; }else {q->_buf =malloc (Default_size *sizeof (void *)); q->capcity = default_size; } Q->header = Q->tail = Q->size =0; }return q;}IntQueue_is_full(queue_t *q) {return q->size = = q->capcity;}IntQueue_is_empty(queue_t *q) {return q->size = =0;}voidQueue_push_tail(queue_t *q,void *data) {if (!queue_is_full (q)) {Q->_buf[q->tail] = data; Q->tail = (Q->tail +1)% q->capcity; q->size++; }}void *queue_pop_head(queue_t *q) { void *data = NULL; if (!queue_is_empty (q)) {data = q->_buf[(Q->header)]; Q->header = (Q->header + 1)% q->capcity; Q >size--; } return data; int *queue_free(queue_t *q) {free (Q->_BUF); Free (q);}               
asynchronous queues implemented by thread variables
typedefstructasync_queue{pthread_mutex_t Mutex; pthread_cond_t cond;int waiting_threads; queue_t *_queue;} async_queue_t;async_queue_t *async_queue_create (int size) {async_queue_t *q = malloc (sizeof (async_queue_t)); Q->_queue = queue_create (size); Q->waiting_threads =0; Pthread_mutex_init (& (Q->mutex), NULL); Pthread_cond_init (& (Q->cond), NULL);return q;} void Async_queue_push_tail (async_queue_t *q, void *data) {if (!queue_is_full (Q->_queue)) {Pthread_mutex_lock (& (Q->mutex)); Queue_push_tail (q->_queue, data);if (Q->waiting_threads > 0) {pthread_cond_signal (& (Q->cond));} pthread_mutex_unlock (& (Q- >mutex)); }}void *async_queue_pop_head (async_queue_t *q, struct timeval *tv) {void *retval = NULL; Pthread_mutex_lock ( & (Q->mutex)); if (Queue_is_empty (Q->_queue)) {q->waiting_threads++; while (Queue_is_empty (Q->_queue)) {pthread_cond_wait (& (Q->cond), & (Q->mutex));} q->waiting _threads--; } retval = Queue_pop_head (q->_queue); Pthread_mutex_unlock (& (Q->mutex)); return retval;} void Async_queue_free (async_queue_t *q) {queue_free (q->_queue); Pthread_cond_destroy (& (Q->cond)); pthread _mutex_destroy (& (Q->mutex)); Free (q);}      
Asynchronous queues implemented by EVENTFD
typedefstruct async_queue{int EFD;Event FD Fd_set Rdfds;For selectqueue_t *_queue;}async_queue_t;async_queue_t *async_queue_create (int size) {async_queue_t *q =mallocsizeof (async_queue_t)); Q-&GT;EFD = EVENTFD (0, efd_semaphore| Efd_nonblock); Q->_queue = queue_create (size); Fd_zero (& (Q->rdfds)); Fd_set (Q-&GT;EFD, & (Q->rdfds));return q;}voidAsync_queue_push_tail(async_queue_t *q,void *data) {UnsignedLongLong i =1;if (!queue_is_full (Q->_queue)) {Queue_push_tail (q->_queue, data); write (Q-&GT;EFD, &i,sizeof (i)); }}void *Async_queue_pop_head(async_queue_t *q,struct Timeval *tv) {Unsignedlong Long i = 0; void *data = NULL; if (select (Q->EFD + 1, & (Q->RDFDS), null, NULL, TV) = = 0) { return data;} else {read (Q->EFD, &i, sizeof (i)); return Queue_pop_head (Q->_queue);}} void async_queue_free(async_queue_t *q) {queue_free (q->_queue); close (Q->EFD); Free (q);}                  
Summarize

The two methods of implementing threading condition variables are more complex, but the performance is slightly higher, while the EVENTFD implementation is simple, but the performance is slightly lower.

Implementing queues on Linux platforms

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.