Code:
// Threaded Primes
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#include <semaphore.h>
#include <fcntl.h>
#define Q_SIZE 10
struct queue {
int queue[Q_SIZE];
int front; int back;
sem_t *mutex;
sem_t *slots;
sem_t *items;
};
struct queue queue1;
struct queue queue2;
struct queue queue3;
struct queue queue4;
struct queue queue5;
struct queue queue6;
struct filter {
void *input;
void *output;
int p;
}
void numberFilter(void *filterStruct) { // check #s
int nextNumber;
int number = filterStruct->number;
void *inputQ = filterStruct->inputQ;
void *outputQ = filterStruct->outputQ;
while(1) {
nextNumber = dequeue(inputQ);
if(nextNumber == -1) {
enqueue(number, outputQ);
pthread_exit(0); // stop executing. poison pill received.
}
if(nextNumber == number) enqueue(number, outputQ);
if(nextNumber%number != 0) enqueue(nextNumber, outputQ);
}
}
void generator() { // generate #'s 2 thru 1000
int counter = 2;
while(counter<1001) {
enqueue(counter, queue1);
counter++;
}
enqueue(-1, queue1); // send poison pill
}
void finalCheck(void *inputQ) { // final checker, 13 thru sqrt of #
int nextNumber;
while(1) {
nextNumber = dequeue(inputQ);
if(nextNumber == -1) {
pthread_exit(0); // stop executing. poison pill received.
}
int prime = 1;
for(int i = 13; i<=sqrt(nextNumber); i+=2) {
if(nextNumber%i == 0) prime = 0;
}
if(prime == 1) printf("%d ", nextNumber);
}
}
void initQueue(void *q) {
q.queue[0] = 0;
q.front = 0; q.back = 0;
q.mutex = sem_open("QueueMutex", O_CREAT, 0700, 1); // init mutex sem
if (!q.mutex) {
perror("semaphore create error");
exit(4);
}
q.slots = sem_open("QueueSlots", O_CREAT, 0700, 10); // init slots sem
if (!q.slots) {
perror("semaphore create error");
exit(4);
}
q.items = sem_open("QueueItems", O_CREAT, 0700, 0); // init items sem
if (!q.items) {
perror("semaphore create error");
exit(4);
}
}
void enqueue(int newElement, void *q) {
sem_wait(q.slots); // P(slots) operation.
sem_wait(q.mutex); // P(mutex) operation.
q.queue[back] = newElement;
back = (back+1) % Q_SIZE;
sem_post(q.mutex); // V(mutex) operation.
sem_post(q.items); // V(items) operation.
}
int dequeue(void *q) {
sem_wait(q.items); // P(items) operation.
sem_wait(q.mutex); // P(mutex) operation.
int value = q.queue[q.front];
front = (front+1) % Q_SIZE;
sem_post(q.mutex); // V(mutex) operation.
sem_post(q.slots); // V(slots) operation.
return value;
}
int main() {
initQueue(*queue1);
initQueue(*queue2);
initQueue(*queue3);
initQueue(*queue4);
initQueue(*queue5);
initQueue(*queue6);
struct filter filter2 = {&queue1, &queue2, 2};
struct filter filter3 = {&queue2, &queue3, 3};
struct filter filter5 = {&queue3, &queue4, 5};
struct filter filter7 = {&queue4, &queue5, 7};
struct filter filter11 = {&queue5, &queue6, 11};
generator();
pthread_t thread2;
int k = pthread_create(&thread2, NULL, numberFilter, &filter2);
// creates thread for sorting through 2's.
pthread_t thread3;
int k = pthread_create(&thread3, NULL, numberFilter, &filter3);
// creates thread for sorting through 3's.
pthread_t thread5;
int k = pthread_create(&thread5, NULL, numberFilter, &filter5);
// creates thread for sorting through 5's.
pthread_t thread7;
int k = pthread_create(&thread7, NULL, numberFilter, &filter7);
// creates thread for sorting through 7's.
pthread_t thread11;
int k = pthread_create(&thread11, NULL, numberFilter, &filter11);
// creates thread for sorting through 11's.
pthread_t threadFinal;
int k = pthread_create(&threadFinal, NULL, finalCheck, &queue6);
// creates thread for final check.
}