Atomic Operation: An atomic operation is something that is not interruptable and occurs in isolation from other operations.
thread-safe operation: A thread-safe operation (or set of operations) has the property that if used by multiple threads, no problems will occur.
async-safe operation: An async-safe operation (also called reentrant in some circles) is an operation that can safely be invoked in a signal handler.
What is a pipe?
Semantically, a ring buffer of characters (an array queue).
write enqueues to the buffer.
read dequeues from the buffer.
Thread-safety and async safety.
simultaneous usability by multiple processes.
block on read from empty buffer.
block on write to full buffer.
Bounded buffer queue
This is a basic building block for all producer/consumer programs.
// sharing a queue between threads #include <stdio.h>#include <string.h>#include <pthread.h>// canonical solution to deadlock-free producer-consumer // coding, using three locks pthread_mutex_t can_modify;// whether I can modify queue contents pthread_mutex_t can_dequeue;// locked if queue is emptypthread_mutex_t can_enqueue;// locked if queue is full #define SIZE 20int begin=0, end=0;charqueue[SIZE];// extent of queueintempty(){return begin==end;}// is queue empty? intfull(){return((end+1)%SIZE)==begin;}// is queue full? voidenqueue(charc){// how to enqueue a characterpthread_mutex_lock(&can_enqueue);// wait until there is spacepthread_mutex_lock(&can_modify);// wait until you can modify//////////////////BEGIN CRITICAL SECTION int empty_before=empty();queue[end]=c; end=(end+1)%SIZE;int full_after=full();//////////////////END CRITICAL SECTION pthread_mutex_unlock(&can_modify);if(empty_before){// if it was empty before, pthread_mutex_unlock(&can_dequeue);// it is not empty now. }if(!full_after){// if it is not full after, pthread_mutex_unlock(&can_enqueue);// there is still space.}}chardequeue(){// how to dequeue a characterchar out;pthread_mutex_lock(&can_dequeue);// wait until you can dequeuepthread_mutex_lock(&can_modify);// wait until you can modify//////////////////BEGIN CRITICAL SECTION int full_before =full(); out =queue[begin]; begin=(begin+1)%SIZE;int empty_after =empty();//////////////////END CRITICAL SECTION pthread_mutex_unlock(&can_modify);if(full_before){// if it was full before,pthread_mutex_unlock(&can_enqueue);// then it is not full now.}if(!empty_after){// if it was not empty after, pthread_mutex_unlock(&can_dequeue);// there is something to dequeue}return out;}