ch4-job-queue3

Chapter_4     job-queue2 spin-condvar







job-queue3.c     ALP, p. 81-83


#include <stdio.h> // for printf(), NULL
#include <malloc.h> // for malloc(), free()
#include <pthread.h> // for pthread_t, pthread_create(), pthread_join(),
// pthread_mutex_t, PTHREAD_MUTEX_INITIALIZER, pthread_mutex_lock(),
// pthread_mutex_unlock()
// pthread.h includes bits/pthreadtypes.h, full path
// /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h,
// which defines pthread_t and pthread_mutex_t
#include <semaphore.h> // for sem_t, sem_init(), sem_post(), sem_wait()
// semaphore.h includes bits/semaphore.h, full path
// /usr/include/x86_64-linux-gnu/bits/semaphore.h,
// which defines sem_t

struct job
{
struct job * next; // Link field for linked list
int number;
/* Other fields describing work to be done... */
};

struct job * job_queue; // A linked list of pending jobs
/* A mutex protecting job_queue: */
pthread_mutex_t job_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
/* A semaphore counting the number of jobs in the queue: */
sem_t job_queue_count;

/* Perform one-time initialization of the job queue: */
void initialize_job_queue()
{
job_queue = NULL; // The queue is initially empty
sem_init (&job_queue_count, 0, 0); // initialize semaphore to 0
}

/* Add a new job to the front of the job queue. */
void enqueue_job (/* Pass job-specific data here... */ int);

/* Process queued jobs until the queue is empty: */
void * thread_function (void * arg);

int main()
{ // initialize the job queue:
enqueue_job(2); // add last (second) job to the queue
enqueue_job(1); // add first job to the queue

pthread_t thread;
pthread_create (&thread, NULL, &thread_function, NULL);
pthread_join (thread, NULL);

return 0;
}

/* Add a new job to the front of the job queue. */
void enqueue_job (/* Pass job-specific data here... */ int n)
{
struct job * new_job;
/* Allocate a new job object: */
new_job = (struct job*) malloc (sizeof (struct job));
/* Set the other fields of the job struct here... */
new_job->number = n;
/* Lock the mutex on the job queue before accessing it: */
pthread_mutex_lock (&job_queue_mutex);
/* Place the new job at the head of the queue: */
new_job->next = job_queue;
job_queue = new_job;
/* Post to the semaphore to indicate that another job is available. If
threads are blocked, waiting on the semaphore, one will become
unblocked so it can process the job. */
sem_post (&job_queue_count);
/* Unlock the job queue mutex: */
pthread_mutex_unlock (&job_queue_mutex);
}

void process_job (struct job *);

/* Process queued jobs until the queue is empty: */
void* thread_function (void* arg)
{
struct job * next_job;

while(1)
{
/* Wait on the job queue semaphore. If its value is positive,
indicating that the queue is not empty, decrement the count by 1.
If the queue is empty, block until a new job is enqueued. */
sem_wait (&job_queue_count);

/* Lock the mutex on the job queue: */
pthread_mutex_lock (&job_queue_mutex);
// Because of the semaphore, we know the queue is not empty:
next_job = job_queue; // Get the next available job
job_queue = job_queue->next; // Remove this job from the list
/* Unlock the mutex on the job queue because we're done with the
queue for now: */
pthread_mutex_unlock (&job_queue_mutex);
process_job (next_job); // Carry out the work
free(next_job); // Clean up
}

return NULL;
}

void process_job (struct job * current)
{
printf("Processing job %d...\n", current->number);
}
/*
gcc job-queue3.c -o job-queue3 -lpthread
./job-queue3
Processing job 1...
Processing job 2...
^C // Ctrl^C
*/









Chapter_4     job-queue2 BACK_TO_TOP spin-condvar



Comments

Popular posts from this blog

Contents