以下是APUE线程章节中,简单实现多工作线程获取工作队列源码!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/***************************
* Define the job structure
**************************/
struct job {
struct job *j_next;
struct job *j_prev;
pthread_t j_pid;
};
/***************************
* Define the queue
* structure.
**************************/
struct queue {
struct job *q_head;
struct job *q_tail;
pthread_rwlock_t q_rwlock;
};
// Initialize a queue
int queue_init( struct queue *qp)
{
int err;
qp->q_head = NULL;
qp->q_tail = NULL;
if((err = pthread_rwlock_init(&qp->q_rwlock, NULL)) != 0){
perror("pthread_rwlock_init");
return err;
}
return (0);
}
// Insert a job at the head of the queue.
void job_insert(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_rwlock);
jp->j_next = qp->q_head;
jp->j_prev = NULL;
if(qp->q_head == NULL) {
qp->q_tail = jp;
} else {
qp->q_head->j_prev = jp;
}
qp->q_head = jp;
pthread_rwlock_unlock(&qp->q_rwlock);
return ;
}
// Append a job on the queue
void job_append(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_rwlock);
jp->j_prev = qp->q_tail;
jp->j_next = NULL;
if(qp->q_tail == NULL) {
qp->q_head = jp;
} else {
qp->q_tail->j_next = jp;
}
qp->q_tail = jp;
pthread_rwlock_unlock(&qp->q_rwlock);
}
// Remove the given job from a queue
// remind: just remove the job from queue
// don't free the space of the job
void job_remove(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_rwlock);
if(jp == qp->q_head) {
qp->q_head = jp->j_next;
if(qp->q_tail == jp){
qp->q_tail = NULL;
}
} else if(jp == qp->q_tail) {
qp->q_tail = jp->j_prev;
if(qp->q_head == jp){
qp->q_head == NULL;
}
} else {
jp->j_prev->j_next = jp->j_next;
jp->j_next->j_prev = jp->j_prev;
}
pthread_rwlock_unlock(&qp->q_rwlock);
}
// given a known pid, find out the job
struct job * job_find (struct queue *qp, pthread_t pid)
{
struct job *jp = NULL;
pthread_rwlock_rdlock(&qp->q_rwlock);
for(jp = qp->q_head; jp != NULL; jp = jp->j_next){
if(pthread_equal(pid, jp->j_pid))
break;
}
pthread_rwlock_unlock(&qp->q_rwlock);
return (jp);
}