#include <stdio.h> // for printf(), NULL
#include <malloc.h> // for malloc(), free()
#include <pthread.h> // for pthread_t, pthread_create(), pthread_join()
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
/* Process queued jobs until the queue is empty: */
void * thread_function (void * arg);
int main()
{ // initialize the job queue:
struct job *job1, *job2;
job1 = (struct job *) malloc(sizeof(struct job));
job2 = (struct job *) malloc(sizeof(struct job));
job1->number = 1, job1->next = job2;
job2->number = 2, job2->next = NULL; // last job in the queue
job_queue = job1; // first job to be done
pthread_t thread;
pthread_create (&thread, NULL, &thread_function, NULL);
pthread_join (thread, NULL);
return 0;
}
void process_job (struct job *);
/* Process queued jobs until the queue is empty: */
void* thread_function (void* arg)
{
struct job * next_job;
while (job_queue != NULL)
{
next_job = job_queue; // Get the next available job
job_queue = job_queue->next; // Remove this job from the list
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-queue1.c -o job-queue1 -lpthread
./job-queue1
Processing job 1...
Processing job 2...
*/
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
#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
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;
void enqueue_job (struct job * new_job); // add new job to the queue
/* Process queued jobs until the queue is empty: */
void * thread_function (void * arg);
int main()
{ // initialize the job queue:
struct job *job1, *job2;
job1 = (struct job *) malloc(sizeof(struct job));
job2 = (struct job *) malloc(sizeof(struct job));
job1->number = 1, job2->number = 2;
job_queue = job1->next = job2->next = NULL;
enqueue_job(job2); // add last (second) job to the queue
enqueue_job(job1); // add first job to the queue
pthread_t thread;
pthread_create (&thread, NULL, &thread_function, NULL);
pthread_join (thread, NULL);
return 0;
}
void enqueue_job (struct job * new_job) // add new job to the queue
{
pthread_mutex_lock (&job_queue_mutex);
new_job->next = job_queue;
job_queue = new_job;
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)
{
/* Lock the mutex on the job queue: */
pthread_mutex_lock (&job_queue_mutex);
/* Now it's safe to check if the queue is empty: */
if (job_queue == NULL)
{next_job = NULL;}
else
{
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);
/* Was the queue empty? If so, end the thread: */
if (next_job == NULL) // we need to unlock the mutex before breaking
{break;} // out of while(1)
// else
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-queue2.c -o job-queue2 -lpthread
./job-queue2
Processing job 1...
Processing job 2...
*/
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
#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
*/
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
#include <stdio.h> // for printf(), putchar(), fflush(), stdout, NULL
#include <unistd.h> // for sleep()
#include <pthread.h> // for pthread_t, pthread_create(), pthread_mutex_t,
// pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock()
int thread_flag;
pthread_mutex_t thread_flag_mutex;
void initialize_flag(void);
void* thread_function (void* thread_arg);
void set_thread_flag (int flag_value);
int main()
{
int i, flag = 1;
initialize_flag();
set_thread_flag(flag);
pthread_t thread;
pthread_create (&thread, NULL, &thread_function, NULL);
for(i = 0; ; i++) // for ever
{
printf("main ");
fflush(stdout); // flush the output buffer
sleep(1); // pause for 1 second
if (i % 5 == 4) // every 5 seconds
{
putchar('\n');
flag = (flag + 1) % 2; // change state, 0 <--> 1
set_thread_flag(flag);
}
}
return 0;
}
void initialize_flag(void)
{
pthread_mutex_init (&thread_flag_mutex, NULL);
thread_flag = 0;
}
void do_work(void);
/* Calls do_work() repeatedly while the thread flag is set,
otherwise spins */
void* thread_function (void* thread_arg)
{
while(1) // for ever
{
int flag_is_set;
/* Protect the flag with a mutex lock: */
pthread_mutex_lock (&thread_flag_mutex);
flag_is_set = thread_flag;
pthread_mutex_unlock (&thread_flag_mutex);
if (flag_is_set)
{do_work ();}
/* else do nothing, just loop again */
}
return NULL;
}
void do_work(void)
{
printf("work ");
fflush(stdout); // flush the output buffer
sleep(1); // pause for 1 second
}
/* Sets the value of the thread flag to FLAG_VALUE. */
void set_thread_flag (int flag_value)
{
/* Protect the flag with a mutex lock: */
pthread_mutex_lock (&thread_flag_mutex);
thread_flag = flag_value;
pthread_mutex_unlock (&thread_flag_mutex);
}
/*
gcc spin-condvar.c -o spin-condvar -lpthread
./spin-condvar
main work main work main work main work main work
main work main main main main
main work main work main work main work main work
main main main main main
main work main work main work main work main work
main main main main main
main work main work main work main work main work
main main main main main
main work main work main work main work main work
main main main main main
main work main work main work main work main work
main work main main main main
main work main work main work main work work main work
main main ^C // Ctrl^C
*/
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
#include <stdio.h> // for printf(), putchar(), fflush(), stdout, NULL
#include <unistd.h> // for sleep()
#include <pthread.h> // for pthread_t, pthread_cond_t, pthread_mutex_t,
// pthread_cond_init(), pthread_cond_wait(), pthread_cond_signal(),
// pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock(),
// pthread_create()
// pthread.h includes bits/pthreadtypes.h, full path
// /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h,
// which defines pthread_t, pthread_cond_t, and pthread_mutex_t
int thread_flag;
pthread_cond_t thread_flag_cv;
pthread_mutex_t thread_flag_mutex;
void initialize_flag(void);
void* thread_function (void* thread_arg);
void set_thread_flag (int flag_value);
int main()
{
int i, flag = 1;
initialize_flag();
set_thread_flag(flag);
pthread_t thread;
pthread_create (&thread, NULL, &thread_function, NULL);
for(i = 0; ; i++) // for ever
{
printf("main ");
fflush(stdout); // flush the output buffer
sleep(1); // pause for 1 second
if (i % 5 == 4)
{
putchar('\n');
flag = (flag + 1) % 2; // change state, 0 <--> 1
set_thread_flag(flag);
}
}
return 0;
}
void initialize_flag(void)
{
/* Initialize the mutex and condition variable: */
pthread_mutex_init (&thread_flag_mutex, NULL);
pthread_cond_init (&thread_flag_cv, NULL);
/* Initialize the flag value: */
thread_flag = 0;
}
void do_work(void);
/* Calls do_work() repeatedly while the thread flag is set,
blocks if the flag is clear */
void* thread_function (void* thread_arg)
{
while (1) // loop forever
{
/* Lock the mutex before accessing the flag value: */
pthread_mutex_lock (&thread_flag_mutex);
while (!thread_flag)
{
/* The flag is clear. Wait for a signal on the condition
variable, indicating that the flag value has changed. When the
signal arrives and this thread unblocks, loop and check the
flag again. */
pthread_cond_wait (&thread_flag_cv, &thread_flag_mutex);
}
// When we've gotten here, we know the flag must be set
pthread_mutex_unlock (&thread_flag_mutex);
do_work(); /* Do some work */
}
return NULL;
}
void do_work(void)
{
printf("work ");
fflush(stdout);
sleep(1);
}
void set_thread_flag (int flag_value)
{
/* Lock the mutex before accessing the flag value: */
pthread_mutex_lock (&thread_flag_mutex);
/* Set the flag value, and then signal in case thread_function()
is blocked, waiting for the flag to become set. However,
thread_function() can't actually check the flag until the mutex
is unlocked: */
thread_flag = flag_value;
pthread_cond_signal (&thread_flag_cv);
pthread_mutex_unlock (&thread_flag_mutex);
}
/*
gcc condvar.c -o condvar -lpthread
./condvar
main work main work main work main work main work
main work main main main main
main work main work main work main work main work
main main main main main
main work main work work main work main work main
main main main main main
main work work main work main work main work main work
main main main main main
main work main work main work main work main work
main main main main main
main work main work main work main work main work
main work main main main main
main work work main main work main work main work work
main main ^C // Ctrl^C
*/
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
#include <stdio.h> // for fprintf(), stderr, NULL
#include <unistd.h> // for getpid()
#include <pthread.h> // for pthread_t, pthread_create()
void * thread_function (void * arg);
int main()
{
pthread_t thread;
fprintf (stderr, "main() thread pid is %d\n", (int) getpid());
pthread_create (&thread, NULL, &thread_function, NULL);
while(1); /* Spin forever. */
return 0;
}
void * thread_function (void * arg)
{
fprintf (stderr, "child thread pid is %d\n", (int) getpid());
while(1); /* Spin forever. */
return NULL;
}
/*
gcc thread-pid.c -o thread-pid -lpthread
./thread-pid
main() thread pid is 100092
child thread pid is 100092
^C // Ctrl^C
*/