복잡 한 생산자 소비자 - pthread

기초 지식 사고 정리http://blog.csdn.net/aganlengzi/article/details/51416461
/*
          :
         ,        (     )         ,
             (     )      .
       pthread     
           
           
           
         
*/

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define PRODUCER_NUM 3 //     
#define CONSUMER_NUM 2 //     
#define ITEM_NUM 5 //       
#define DELAY_TIME 3 //    
#define QUEUE_SIZE (ITEM_NUM + 1) //    

typedef int ElemType;

/* head           tail        empty: head == tail full: (tial + 1)%QUEUE_SIZE == head insert: not full --> elem[++tail] = inserted_num delete: not empty --> delete[++head] */
typedef struct 
{
    ElemType elem[QUEUE_SIZE];
    int head, tail;
}Queue;

Queue the_queue, *p_queue;
pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t producer_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t consumer_cond = PTHREAD_COND_INITIALIZER;

int ERROR_CODE;

/* func : init the queue input : Queue *p_queue output: none */
void init_queue(Queue *p_queue)
{
    memset(p_queue, 0, sizeof(*p_queue));
}

/*
  func  : judge if queue full
  input : Queue* p_queue
  output: 0 not full
          1 is full
 */
int is_queue_full(Queue *p_queue)
{
    if(p_queue->head == (p_queue->tail + 1)% QUEUE_SIZE)
        return 1;
    else
        return 0;
}

/*
  func  : judge if queue empty
  input : Queue* p_queue
  output: 0 not empty
          1 is empty
 */
int is_queue_empty(Queue *p_queue)
{
    if(p_queue->head == p_queue->tail)
        return 1;
    else
        return 0;
}

/*
  func  : get total elem num
  input : Queue* p_queue
  output: num of elem
 */
int get_queue_num(Queue *p_queue)
{
    return (p_queue->tail + QUEUE_SIZE - p_queue->head)%QUEUE_SIZE;
}

/*
  func  : insert an elem into the queue
  input : Queue* p_queue, inserted_elem
  output: 0 and ERROR_CODE=-1: full and wrong
          1: sucess
 */
int insert_queue(Queue *p_queue, ElemType inserted_elem)
{
    if(is_queue_full(p_queue))
    {
        printf("The queue is full
"
); ERROR_CODE = -1; return 0; } else { p_queue->tail += 1; p_queue->tail %= QUEUE_SIZE; p_queue->elem[p_queue->tail] = inserted_elem; return 1; } } /* func : delete an elem from the queue input : Queue* p_queue output: 0 and ERROR_CODE = -1: empty and wrong other: deleted elem */ int delet_queue(Queue *p_queue) { if(is_queue_empty(p_queue)) { printf("The queue is empty
"
); ERROR_CODE = -1; return 0; } else { p_queue->head += 1; p_queue->head %= QUEUE_SIZE; return p_queue->elem[p_queue->head]; } } /* func : get tail of the queue input : Queue* p_queue output: the tail of the queue */ int get_queue_tail(Queue *p_queue) { return p_queue->tail; } /* func : get head of the queue input : Queue* p_queue output: the head of the queue */ int get_queue_head(Queue *p_queue) { return p_queue->head; } /* func : the consumer thread, detached and is a dead loop input : void *para, the index of the all_threads array convenient for locating output: void * */ void * consumer_thread(void *para) { long thread_no = (long)para; while(1) { pthread_mutex_lock(&queue_lock); while(is_queue_empty(p_queue)) { pthread_cond_wait(&consumer_cond, &queue_lock); } delet_queue(p_queue); if(get_queue_num(p_queue) == ITEM_NUM - 1) { pthread_cond_broadcast(&producer_cond); } printf("consumer thread[%ld] deletes queue[%d]=%d
"
, thread_no, p_queue->head, p_queue->elem[p_queue->head]); pthread_mutex_unlock(&queue_lock); sleep(rand()%DELAY_TIME + 1); } } /* func : the producer thread, detached and is a dead loop input : void *para, the index of the all_threads array convenient for locating output: void * */ void * producer_thread(void *para) { long thread_no = (long)para; int tmp; while(1) { pthread_mutex_lock(&queue_lock); while(is_queue_full(p_queue)) { pthread_cond_wait(&producer_cond, &queue_lock); } tmp = get_queue_tail(p_queue); insert_queue(p_queue, tmp); if(get_queue_num(p_queue) == 1) { pthread_cond_broadcast(&consumer_cond); } printf("producer thread[%ld] produces queue[%d]=%d
"
, thread_no, p_queue->tail, tmp ); pthread_mutex_unlock(&queue_lock); sleep(rand()%DELAY_TIME + 1); } } int main(int argc, char const *argv[]) { // using pointer but not the variable p_queue = &the_queue; // storing all the ids of the threads pthread_t all_threads[CONSUMER_NUM + PRODUCER_NUM]; // attributes pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // tmp index int index; init_queue(p_queue); // creating the consumers for (index = 0; index < CONSUMER_NUM; ++index) { pthread_create(&all_threads[index], &attr, consumer_thread, (void*)index); } sleep(2); // creating the producers for (index = 0; index < PRODUCER_NUM; ++index) { pthread_create(&all_threads[index + CONSUMER_NUM], &attr, producer_thread, (void*)index); } //destroy the initialized attribute variable pthread_attr_destroy(&attr); //pthread_exit(NULL); while(1); return 0; }

[1] http://www.cnblogs.com/clover-toeic/p/4029269.html

좋은 웹페이지 즐겨찾기