Commit a871d870 authored by Mark Laptop's avatar Mark Laptop

provided files for the True Concurrency Tutorial: Concurrent Sieve of Eratosthenes

parents
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>
#include "Index.h"
//---------------------------------------------------------------------------\\
void *thread_1_work(void * index_ptr) {
// extract worker arguments
struct index *idx = (struct index *) index_ptr;
bool b;
// loops adding and removing 1 from the index, searching in-between
for(int cnt = 1; cnt <= 100; cnt++){
b = index_insert(idx, 1);
printf("t1:insert 1 : %s\n", b ? "true" : "false");
b = index_search(idx, 1);
printf("t1:search 1 : %s\n", b ? "true" : "false");
b = index_remove(idx, 1);
printf("t1:remove 1 : %s\n", b ? "true" : "false");
b = index_search(idx, 1);
printf("t1:search 1 : %s\n", b ? "true" : "false");
b = index_insert(idx, 1);
printf("t1:insert 1 : %s\n", b ? "true" : "false");
b = index_search(idx, 1);
printf("t1:search 1 : %s\n", b ? "true" : "false");
}
printf("thread 1 finished!\n");
// this function must return something
return NULL;
}
void *thread_2_work(void * index_ptr) {
// extract worker arguments
struct index *idx = (struct index *)index_ptr;
bool b;
// loops adding and removing 2 from the index with pauses to search
for(int cnt = 1; cnt<=100; cnt++){
b = index_insert(idx, 2);
printf("t2:insert 2 : %s\n", b ? "true" : "false");
b = index_search(idx, 2);
printf("t2:search 2 : %s\n", b ? "true" : "false");
b = index_remove(idx, 2);
printf("t2:remove 2 : %s\n", b ? "true" : "false");
b = index_search(idx, 2);
printf("t2:search 2 : %s\n", b ? "true" : "false");
b = index_insert(idx, 2);
printf("t2:insert 2 : %s\n", b ? "true" : "false");
b = index_search(idx, 2);
printf("t2:search 2 : %s\n", b ? "true" : "false");
}
printf("thread 2 finished!\n");
// this function must return something
return NULL;
}
void *thread_3_work(void * index_ptr) {
// extract worker arguments
struct index *idx = (struct index *)index_ptr;
bool b;
// disruptive loop adding and removing 1 and 2 from the index
for(int cnt = 1; cnt<=100; cnt++){
b = index_insert(idx, 1);
printf("t3:insert 1 : %s\n", b ? "true" : "false");
b = index_insert(idx, 2);
printf("t3:insert 2 : %s\n", b ? "true" : "false");
b = index_remove(idx, 1);
printf("t3:remove 1 : %s\n", b ? "true" : "false");
b = index_remove(idx, 2);
printf("t3:remove 2 : %s\n", b ? "true" : "false");
b = index_insert(idx, 1);
printf("t3:insert 1 : %s\n", b ? "true" : "false");
b = index_insert(idx, 2);
printf("t3:insert 2 : %s\n", b ? "true" : "false");
}
printf("thread 3 finished!\n");
// this function must return something
return NULL;
}
int main(int argc, char ** argv) {
printf("Basic Concurrent Index Test\n");
// Idea: start up 3 threads and have them all hit the index simultaneously.
struct index my_index;
index_init(&my_index, NULL, 0);
// check the initial state of the index
printf("print index forwards:\n");
index_print(&my_index, '<');
printf("\n");
printf("starting 3 threads that concurrently modify the index...\n");
// initialise references to the worker threads
pthread_t thread_1;
pthread_t thread_2;
pthread_t thread_3;
// create the worker threads
pthread_create(&thread_1, NULL, thread_1_work, &my_index);
pthread_create(&thread_2, NULL, thread_2_work, &my_index);
pthread_create(&thread_3, NULL, thread_3_work, &my_index);
// wait for the worker threads to complete
pthread_join(thread_1, NULL);
pthread_join(thread_2, NULL);
pthread_join(thread_3, NULL);
// check the final state of the index
printf("print index forwards:\n");
index_print(&my_index, '<');
printf("\n");
printf("print index backwards:\n");
index_print(&my_index, '>');
printf("\n");
}
#include "Index.h"
#include <stdio.h>
#include <malloc.h>
#include <limits.h>
#include <sched.h>
//---------------------------------------------------------------------------\\
// Index implementation
void index_init(struct index *idx, int seeds[], int length){
idx->head = NULL;
idx->tail = NULL;
// insert the seed elements into the index
for(int i=0; i<length; i++){
index_insert(idx, seeds[i]);
}
}
bool index_search(struct index *idx, int key){
// set-up for index traversal
struct node *cur = NULL;
struct node *nxt = idx->head;
int item = INT_MIN;
// traverse the index elements
while(nxt != NULL && item < key ){
cur = nxt;
nxt = cur->next;
item = cur->item;
if(item == key){
// found it!
return true;
}
}
// item not in the index so, did not find it
return false;
}
bool index_insert(struct index *idx, int key){
// create basic Node
struct node *new_node = malloc(sizeof(struct node));
if(new_node == NULL){
printf("ERROR: out of memory!\n");
return false;
}
new_node->prev = NULL;
new_node->next = NULL;
new_node->item = key;
// special case for empty index
if(idx->head == NULL && idx->tail == NULL){
idx->head = new_node;
idx->tail = new_node;
return true;
}
// set-up for index traversal
struct node *prv = NULL;
struct node *cur = NULL;
struct node *nxt = idx->head;
// traverse the index elements
while(nxt != NULL){
prv = cur;
cur = nxt;
nxt = cur->next;
int item = cur->item;
if(item == key){
// we do not duplicate items in the index
free(new_node);
return false;
}
if(item > key){
// found where the new item should go
// update new Node pointers (dangles off of list for now)
new_node->prev = prv;
new_node->next = cur;
// update back pointer of current element
cur->prev = new_node;
// Note: at this point the list's pointer structure is inconsistent!
sched_yield(); // demonic scheduling here will really mess us up!
// update forward pointer of prev element (or list head)
if(prv != NULL){
prv->next = new_node;
} else {
idx->head = new_node;
}
return true;
}
// goto next element
}
// if not inserted in loop then item belongs on the end of the list
idx->tail->next = new_node;
new_node->prev = idx->tail;
idx->tail = new_node;
return true;
}
bool index_remove(struct index *idx, int key){
// set-up for index traversal
struct node *prv = NULL;
struct node *cur = NULL;
struct node *nxt = idx->head;
// traverse the index elements
while(nxt != NULL){
prv = cur;
cur = nxt;
nxt = cur->next;
int item = cur->item;
// check each item
if(item == key){
// found the item to be removed
// update back pointer of next element (or list tail)
if(nxt != NULL){
nxt->prev = prv;
} else {
idx->tail = prv;
}
// Note: at this point the list's pointer structure is inconsistent!
sched_yield(); // demonic scheduling here will really mess us up!
// update forward pointer of prev element (or list head)
if(prv != NULL){
prv->next = nxt;
} else {
idx->head = nxt;
}
// free up memory for Node object
free(cur);
return true;
}
}
// item not in the index, so did not remove it
return false;
}
void index_print(struct index *idx, char order){
struct node *start;
// configure traversal order
if(order == '<'){
start = idx->head;
} else if(order == '>'){
start = idx->tail;
} else {
printf("ERROR: unrecognised input order %c\n", order);
return;
}
// set-up for index traversal
struct node *cur = NULL;
struct node *nxt = start;
printf("|--");
// traverse the index elements
while(nxt != NULL){
// show internal links
if(nxt != start){
printf("<-->");
}
// update next item in the list (depending on traversal order)
cur = nxt;
if(order == '<'){
nxt = cur->next;
} else {
nxt = cur->prev;
}
// print the current item
printf("|·|%i|·|", cur->item);
}
// finish the index traversal
printf("--|\n");
}
#ifndef INDEX_H
#define INDEX_H
#include <stdbool.h>
#include <pthread.h>
// The node struct implements a Doubly-Linked-List element
struct node {
// index key of the node
int item;
// pointers to previous/next nodes in the list
struct node *prev;
struct node *next;
};
// The index struct provides a wrapper for a Concurrent Doubely-Linked-List
// implementation
struct index {
// pointers to the head and tail of the doubly linked list
struct node *head;
struct node *tail;
};
// initialise index IDX from the provided array SEEDS of size LENGTH
void index_init(struct index *idx, int seeds[], int length);
// look for element with KEY in the index IDX
bool index_search(struct index *idx, int key);
// add element with KEY (in order) to the index IDX
bool index_insert(struct index *idx, int key);
// remove element with KEY from the index IDX
bool index_remove(struct index *idx, int key);
// output the contents of the index IDX (pretty-printed) in specified ORDER
void index_print(struct index *idx, char order);
#endif
#include <stdio.h>
#include <stdbool.h>
#include "Index.h"
//---------------------------------------------------------------------------\\
int main(int argc, char ** argv) {
printf("Basic Index Tests\n");
// Idea: create a simple index,
// search for some things,
// remove some things,
// then search again.
printf("Testing the node struct basics\n");
struct node my_node;
my_node.item = 15;
printf("my_node's item is: %i\n\n", my_node.item);
printf("Testing the index basics\n\n");
int seed_data[] = {2,4,1,3,9,11,2,2,2,20};
struct index my_index;
index_init(&my_index, seed_data, 10);
printf("print index forwards:\n");
index_print(&my_index, '<');
printf("\n");
printf("print index backwards:\n");
index_print(&my_index, '>');
printf("\n");
for(int i = 0; i<10; i++){
bool b = index_search(&my_index, i);
printf("search %i: %s\n", i, b ? "true" : "false");
}
printf("----------\n");
for(int i = 0; i<10; i++){
bool b = index_remove(&my_index, i);
printf("remove %i: %s\n", i, b ? "true" : "false");
}
printf("----------\n");
for(int i = 0; i<10; i++){
bool b = index_search(&my_index, i);
printf("search %i: %s\n", i, b ? "true" : "false");
}
printf("\n");
printf("print index forwards:\n");
index_print(&my_index, '<');
printf("\n");
printf("print index backwards:\n");
index_print(&my_index, '>');
printf("\n");
}
all: sequential_index concurrent_index sieve
sequential_index: Main.o Index.o
gcc Main.o Index.o -o sequential_index -lpthread
concurrent_index: Conc.o Index.o
gcc Conc.o Index.o -o concurrent_index -lpthread
sieve: Sieve.o Index.o
gcc Sieve.o Index.o -o sieve -lpthread -lm
Index.o: Index.h Index.c
Main.o: Main.c Index.h
Conc.o: Conc.c Index.h
Sieve.o: Sieve.c Index.h
%.o: %.c
gcc -c $< -lpthread
clean:
rm -rf sequential_index concurrent_index sieve *.o
.PHONY: all clean
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#include "Index.h"
//---------------------------------------------------------------------------\\
// -----------------------------------------------------------------
// TODO: write any additional structs or support functions here...
// -----------------------------------------------------------------
int main(int argc, char ** argv)
{
printf("Sieve of Eratosthenes Example\n");
// Main idea: Sieve of Eratosthenes for first n primes (where n is user input)
if(argv[1] == NULL){
printf(" ERROR: no input max provided!\n");
return -1;
}
int max = atoi(argv[1]);
printf(" finding primes from 2 .. %i\n", max);
// Create an index containing all numbers from 2 .. max
struct index sieve_data;
index_init(&sieve_data, NULL, 0);
// -------------------------------
// TODO: write your code here...
// -------------------------------
printf("\n");
// When all threads have terminated, print out the final state of the index.
// All of the values that are left in the index must be prime numbers.
printf("print index forwards:\n");
index_print(&sieve_data, '<');
printf("\n");
printf("print index backwards:\n");
index_print(&sieve_data, '>');
printf("\n");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment