mirror of
https://github.com/13hannes11/UU_la_parallel_programming_practical_assignments.git
synced 2024-09-04 00:50:58 +02:00
Bolier plate for C++ project added
This commit is contained in:
110
Assignment_1/adt_set.cpp
Normal file
110
Assignment_1/adt_set.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include<iostream>
|
||||
#include<set>
|
||||
#include<stdexcept>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum methodname {add, rmv, ctn};
|
||||
typedef struct _operation{
|
||||
//blah blah blah
|
||||
methodname method;
|
||||
int input;
|
||||
bool output;
|
||||
} operation;
|
||||
|
||||
class ADT_Set {
|
||||
std::set<int> set;
|
||||
public:
|
||||
ADT_Set();
|
||||
void do_op(operation *op);
|
||||
void add(int element, bool output);
|
||||
void rmv(int element, bool output);
|
||||
void ctn(int element, bool output);
|
||||
};
|
||||
|
||||
ADT_Set::ADT_Set() {
|
||||
set = { };
|
||||
}
|
||||
|
||||
void ADT_Set::do_op(operation *op) {
|
||||
switch (op->method) {
|
||||
case methodname::add:
|
||||
add(op->input, op->output);
|
||||
break;
|
||||
case methodname::rmv:
|
||||
rmv(op->input, op->output);
|
||||
break;
|
||||
case methodname::ctn:
|
||||
ctn(op->input, op->output);
|
||||
break;
|
||||
//default:
|
||||
// throw invalid_argument("Uknown operation");
|
||||
}
|
||||
}
|
||||
|
||||
void ADT_Set::add(int element, bool output){
|
||||
bool elem_in_set = set.find(element) != set.end();
|
||||
|
||||
// Element in set -> output must be false
|
||||
// Element not in set - > output must be true
|
||||
if(elem_in_set != output) {
|
||||
set.insert(element);
|
||||
} else {
|
||||
std::ostringstream oss;
|
||||
oss << std::boolalpha << "Invalid operation: add " << element << " " << output;
|
||||
throw invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void ADT_Set::rmv(int element, bool output){
|
||||
bool elem_in_set = set.find(element) != set.end();
|
||||
// Element in set -> output must be true
|
||||
// Element not in set - > output must be false
|
||||
if(elem_in_set == output) {
|
||||
set.erase(element);
|
||||
} else {
|
||||
std::ostringstream oss;
|
||||
oss << std::boolalpha << "Invalid operation: rmv " << element << " " << output;
|
||||
throw invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void ADT_Set::ctn(int element, bool output){
|
||||
bool elem_in_set = set.find(element) != set.end();
|
||||
// Element in set -> output must be true
|
||||
// Element not in set - > output must be false
|
||||
if(elem_in_set != output) {
|
||||
std::ostringstream oss;
|
||||
oss << std::boolalpha << "Invalid operation: ctn " << element << " " << output;
|
||||
throw invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
operation create_random_operation() {
|
||||
methodname method;
|
||||
switch (rand() % 2) {
|
||||
case 0:
|
||||
method = methodname::add;
|
||||
break;
|
||||
case 1:
|
||||
method = methodname::rmv;
|
||||
break;
|
||||
default:
|
||||
method = methodname::ctn;
|
||||
break;
|
||||
}
|
||||
|
||||
int element = rand() % 10;
|
||||
return {
|
||||
.method = method, .input = element, .output = NULL
|
||||
};
|
||||
}
|
||||
|
||||
void fill_with_operations(operation * arr, int arr_size) {
|
||||
int arrSize = arr_size;
|
||||
for (int i = 0; i < arrSize; i++) {
|
||||
arr[i] = create_random_operation();
|
||||
}
|
||||
}
|
||||
80
Assignment_1/concurrent_set.cpp
Normal file
80
Assignment_1/concurrent_set.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <mutex>
|
||||
//#include"set.cpp"
|
||||
//#include"adt_set.cpp"
|
||||
|
||||
class ConcurrentSet {
|
||||
Set cset;
|
||||
std::mutex cmut;
|
||||
|
||||
public:
|
||||
ConcurrentSet();
|
||||
bool do_op(methodname method, int input);
|
||||
bool add(int element);
|
||||
bool rmv(int element);
|
||||
bool ctn(int element);
|
||||
};
|
||||
ConcurrentSet::ConcurrentSet(){
|
||||
cset = Set();
|
||||
}
|
||||
|
||||
bool ConcurrentSet::do_op(methodname method, int input){
|
||||
switch (method) {
|
||||
case methodname::add:
|
||||
return add(input);
|
||||
case methodname::rmv:
|
||||
return rmv(input);
|
||||
break;
|
||||
case methodname::ctn:
|
||||
return ctn(input);
|
||||
default:
|
||||
throw std::invalid_argument("Uknown operation");
|
||||
}
|
||||
}
|
||||
|
||||
bool ConcurrentSet::add(int element) {
|
||||
bool res;
|
||||
cmut.lock();
|
||||
res = cset.add(element);
|
||||
cmut.unlock();
|
||||
return res;
|
||||
}
|
||||
bool ConcurrentSet::rmv(int element) {
|
||||
bool res;
|
||||
cmut.lock();
|
||||
res = cset.rmv(element);
|
||||
cmut.unlock();
|
||||
return res;
|
||||
}
|
||||
bool ConcurrentSet::ctn(int element) {
|
||||
bool res;
|
||||
cmut.lock();
|
||||
res = cset.ctn(element);
|
||||
cmut.unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
void conc_worker_func(int num, operation * test_case, int test_case_count, int worker_count){//note that arrays are passed as pointers
|
||||
int arrSize = test_case_count;
|
||||
for (int i = 0; i < arrSize; i++) {
|
||||
q_mutex.lock();
|
||||
bool output = worker_set.do_op(test_case[i].method, test_case[i].input);
|
||||
done_queue.push({ .method = test_case[i].method, .input = test_case[i].input, .output = output});
|
||||
q_mutex.unlock();
|
||||
}
|
||||
q_mutex.lock();
|
||||
done_count += 1;
|
||||
cout<<"Worker "<<num<<endl;
|
||||
q_mutex.unlock();
|
||||
}
|
||||
|
||||
int test_concurrent_set() {
|
||||
ConcurrentSet* s = new ConcurrentSet;
|
||||
assert(!s->rmv(1));
|
||||
assert(!s->ctn(1));
|
||||
assert(s->add(1));
|
||||
assert(!s->add(1));
|
||||
assert(s->ctn(1));
|
||||
assert(s->rmv(1));
|
||||
assert(!s->ctn(1));
|
||||
return 1;
|
||||
}
|
||||
41
Assignment_1/helper_code.cpp
Normal file
41
Assignment_1/helper_code.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/**** This is a helper/skeleton code for the assignment ****/
|
||||
/**** Author: Sarbojit Das ****/
|
||||
/**** Compile using command g++ simple_thread.cpp -lpthread ****/
|
||||
|
||||
#include<iostream>
|
||||
#include<thread>
|
||||
|
||||
#include"adt_set.cpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ADT_Set adt_set = ADT_Set();
|
||||
|
||||
void worker_func(int num, operation test_case[]){
|
||||
cout<<"Worker "<<num<<endl;
|
||||
}
|
||||
|
||||
void monitor_func(operation test_case[]){
|
||||
//blah blah blah
|
||||
cout<<"Monitor"<<endl;
|
||||
}
|
||||
|
||||
int main(){
|
||||
int N_Threads = 3;
|
||||
|
||||
thread *worker= new thread[N_Threads];
|
||||
operation test_case[100];
|
||||
//fill test_case with your sequence of operations
|
||||
thread monitor = thread(monitor_func,test_case);
|
||||
|
||||
for (int i=0;i<N_Threads;i++){
|
||||
worker[i]=thread(worker_func,i,test_case);
|
||||
}
|
||||
|
||||
for (int i=0;i<N_Threads;i++){
|
||||
worker[i].join();
|
||||
}
|
||||
|
||||
monitor.join();
|
||||
return 0;
|
||||
}
|
||||
94
Assignment_1/main.cpp
Normal file
94
Assignment_1/main.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include"adt_set.cpp"
|
||||
#include"set.cpp"
|
||||
#include"concurrent_set.cpp"
|
||||
|
||||
#define TEST_CASE_COUNT 1000
|
||||
|
||||
enum program {adt_set, test_one_set, one_thread_set, n_thread_set, concurrent_set};
|
||||
|
||||
int run_adt_set(){
|
||||
ADT_Set adt_set = ADT_Set();
|
||||
operation test_case[6] = {
|
||||
{ methodname::add, 1, true },
|
||||
{ methodname::add, 1, false },
|
||||
{ methodname::ctn, 1, true },
|
||||
{ methodname::rmv, 1, true },
|
||||
{ methodname::ctn, 1, false },
|
||||
{ methodname::rmv, 1, false }
|
||||
};
|
||||
|
||||
for (operation op : test_case) {
|
||||
adt_set.do_op(&op);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_N_thread_set(int N) {
|
||||
int worker_count = N;
|
||||
thread *worker= new thread[worker_count];
|
||||
operation test_case[TEST_CASE_COUNT];
|
||||
|
||||
fill_with_operations(test_case, TEST_CASE_COUNT);
|
||||
|
||||
thread monitor = thread(monitor_func,test_case, worker_count);
|
||||
|
||||
for (int i=0;i<worker_count;i++){
|
||||
worker[i]=thread(worker_func, i, test_case, TEST_CASE_COUNT, worker_count);
|
||||
}
|
||||
|
||||
for (int i=0;i<worker_count;i++){
|
||||
worker[i].join();
|
||||
}
|
||||
|
||||
monitor.join();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_one_thread_set() {
|
||||
return run_N_thread_set(1);
|
||||
}
|
||||
|
||||
int run_N_thread_concurrent_set(int N) {
|
||||
int worker_count = N;
|
||||
thread *worker= new thread[worker_count];
|
||||
operation test_case[TEST_CASE_COUNT];
|
||||
|
||||
fill_with_operations(test_case, TEST_CASE_COUNT);
|
||||
|
||||
thread monitor = thread(monitor_func, test_case, worker_count);
|
||||
|
||||
for (int i=0;i<worker_count;i++){
|
||||
worker[i]=thread(conc_worker_func, i, test_case, TEST_CASE_COUNT, worker_count);
|
||||
}
|
||||
|
||||
for (int i=0;i<worker_count;i++){
|
||||
worker[i].join();
|
||||
}
|
||||
|
||||
monitor.join();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(){
|
||||
program p = program::concurrent_set; // change this
|
||||
|
||||
switch (p) {
|
||||
case program::adt_set:
|
||||
return run_adt_set();
|
||||
break;
|
||||
case program::one_thread_set:
|
||||
return run_one_thread_set();
|
||||
break;
|
||||
case program::n_thread_set:
|
||||
return run_N_thread_set(4);
|
||||
break;
|
||||
case program::test_one_set:
|
||||
return test_set();
|
||||
break;
|
||||
case program::concurrent_set:
|
||||
return run_N_thread_concurrent_set(2);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
129
Assignment_1/set.cpp
Normal file
129
Assignment_1/set.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include<iostream>
|
||||
#include<thread>
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <assert.h>
|
||||
//#include"adt_set.cpp"
|
||||
|
||||
|
||||
class Node {
|
||||
public:
|
||||
int data;
|
||||
Node* next;
|
||||
};
|
||||
|
||||
|
||||
class Set {
|
||||
Node* first;
|
||||
public:
|
||||
Set();
|
||||
bool do_op(methodname method, int input);
|
||||
bool add(int element);
|
||||
bool rmv(int element);
|
||||
bool ctn(int element);
|
||||
};
|
||||
|
||||
Set::Set(){
|
||||
first = new Node(); // dummy node;
|
||||
}
|
||||
|
||||
bool Set::do_op(methodname method, int input){
|
||||
switch (method) {
|
||||
case methodname::add:
|
||||
return add(input);
|
||||
case methodname::rmv:
|
||||
return rmv(input);
|
||||
break;
|
||||
case methodname::ctn:
|
||||
return ctn(input);
|
||||
default:
|
||||
throw std::invalid_argument("Uknown operation");
|
||||
}
|
||||
}
|
||||
|
||||
bool Set::add(int element) {
|
||||
bool element_in_list = ctn(element);
|
||||
if (!element_in_list) {
|
||||
Node* tmp = new Node();
|
||||
tmp->data = element;
|
||||
tmp->next = first->next;
|
||||
first->next = tmp;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool Set::rmv(int element) {
|
||||
Node* current = first;
|
||||
Node* prev = first;
|
||||
while(current != NULL) {
|
||||
prev = current;
|
||||
current = current->next;
|
||||
if (current != NULL && current->data == element) {
|
||||
prev->next = current->next;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Set::ctn(int element) {
|
||||
Node* current = first;
|
||||
while(current != NULL) {
|
||||
current = current->next;
|
||||
if (current != NULL && current->data == element) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::mutex q_mutex;
|
||||
std::queue<operation> done_queue = queue<operation>();
|
||||
int done_count = 0;
|
||||
|
||||
Set worker_set = Set();
|
||||
|
||||
void worker_func(int num, operation * test_case, int test_case_count, int worker_count){//note that arrays are passed as pointers
|
||||
int arrSize = test_case_count;
|
||||
for (int i = 0; i < arrSize; i++) {
|
||||
bool output = worker_set.do_op(test_case[i].method, test_case[i].input);
|
||||
q_mutex.lock();
|
||||
done_queue.push({ .method = test_case[i].method, .input = test_case[i].input, .output = output});
|
||||
q_mutex.unlock();
|
||||
}
|
||||
q_mutex.lock();
|
||||
done_count += 1;
|
||||
cout<<"Worker "<<num<<endl;
|
||||
q_mutex.unlock();
|
||||
}
|
||||
|
||||
void monitor_func(operation test_case[], int worker_count){
|
||||
ADT_Set adt_set = ADT_Set();
|
||||
//blah blah blah
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
q_mutex.lock();
|
||||
if(done_count == worker_count && done_queue.empty()) {
|
||||
done = true;
|
||||
} else if(!done_queue.empty()) {
|
||||
operation op = done_queue.front();
|
||||
done_queue.pop();
|
||||
adt_set.do_op(&op);
|
||||
}
|
||||
q_mutex.unlock();
|
||||
}
|
||||
cout<<"Monitor"<<endl;
|
||||
}
|
||||
|
||||
int test_set() {
|
||||
Set s = Set();
|
||||
assert(!s.rmv(1));
|
||||
assert(!s.ctn(1));
|
||||
assert(s.add(1));
|
||||
assert(!s.add(1));
|
||||
assert(s.ctn(1));
|
||||
assert(s.rmv(1));
|
||||
assert(!s.ctn(1));
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user