Skip to content

Commit b6c780d

Browse files
Add files via upload
1 parent 31dec62 commit b6c780d

File tree

6 files changed

+223
-0
lines changed

6 files changed

+223
-0
lines changed

processcomm/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- This repo is meant to be a code repo for the algorithms used for process synchronisation
2+
- How to prevent deadlocks, mutexes and semaphores.
3+
- consumer-producer is a buffer for producers to give info and consumer to take info, producer needs to know when to sleep and stop producing and consumer needs to know how to and when to stop consuming
4+
- buffer is a shared resource so there should be context sync between both, to prevent a situation where consumer and procucer both sleep.
5+
- CS - critical section.
6+
- Semaphores , mutex are kind of locks, conditional variable , use TSL (Test and set lock instruction) under the hood to user kernel to manage processes.
7+
- COnditional variable doesn't check for wakeup call continuously, thus saving clock cycles.
8+
- When a semaphore is working it disables hardware interrupts, which means semaphores are atomic

processcomm/lockVariable.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include<iostream>
2+
#include<thread>
3+
4+
int lock = 0;
5+
6+
class thread_object{
7+
public:
8+
void operator()(int &x){
9+
for(int i=0;i< 10000000;i++){
10+
while(lock != 0);
11+
lock = 1;//lock acquired
12+
x += 1;
13+
lock = 0; //lock left
14+
}
15+
}
16+
};
17+
/*
18+
for i < 10000 , x = 20000
19+
for i < 10^7 , x = 15758112
20+
*/
21+
22+
int main(){
23+
int x = 0;
24+
thread_object obj;
25+
std::thread t1(obj, std::ref(x)); //Process a
26+
std::thread t2(obj, std::ref(x)); //Process b
27+
28+
t1.join();
29+
t2.join();
30+
31+
std::cout<<"Final value of x:"<<x<<std::endl;
32+
33+
return 0;
34+
}

processcomm/main

53.3 KB
Binary file not shown.

processcomm/petersonSolution.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include<iostream>
2+
#include<thread>
3+
using namespace std;
4+
5+
//this algo solves the problems of concurrency of lockVariable approach and waitTurn approach
6+
7+
#define TRUE 1
8+
#define FALSE 0
9+
#define N 2
10+
11+
int turn = 0;
12+
int interested[N];
13+
int x = 0;
14+
15+
void enter_section(int process){
16+
int other = 1 - process;
17+
interested[other] = TRUE;
18+
turn = process;
19+
while(turn == process && interested[other] == TRUE);
20+
}
21+
22+
void leave_section(int process){
23+
interested[process] = FALSE;
24+
}
25+
26+
class thread_object{
27+
public:
28+
void operator()(int process){
29+
for(int i=0;i<1000000000; i++){
30+
enter_section(process);
31+
x += 1;
32+
cout<<"Thread "<<process<<" "<<x<<endl;
33+
leave_section(process);
34+
}
35+
}
36+
};
37+
38+
int main(){
39+
thread_object obj;
40+
std::thread t1(obj, 0);
41+
std::thread t2(obj, 1);
42+
t1.join();
43+
t2.join();
44+
return 0;
45+
}

processcomm/producerConsumer.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include<iostream>
2+
#include<queue>
3+
#include<thread>
4+
#include<mutex>
5+
#include<condition_variable>
6+
7+
class Semaphore{
8+
private:
9+
std::mutex mutex_m;
10+
std::condition_variable condition_c;
11+
unsigned long count_c = 0; //Initilaized as lock
12+
public:
13+
Semaphore(int value){
14+
count_c = value;
15+
}
16+
void release(){ //one release is called it will run, without context switching, as it is atomic
17+
std::lock_guard<std::mutex> lock(mutex_m);
18+
++count_c;
19+
//type mutex wrapper, automatically locks mutex and when it is out of scope releases it
20+
//ensure that mutex is released even if there is an error
21+
condition_c.notify_one();
22+
}
23+
void acquire(){
24+
std::unique_lock<std::mutex> lock(mutex_m);
25+
while(!count_c) condition_c.wait(lock);// handle spurious wake-ups
26+
--count_c;
27+
}
28+
};
29+
30+
std::mutex mtx;
31+
std::queue<int> buffer;
32+
const unsigned int MAX_BUFFER_SIZE = 10;
33+
34+
Semaphore empty_slots(MAX_BUFFER_SIZE);//semaphore for empty slots
35+
Semaphore filled_slots(0);//semaphore for filled slots
36+
37+
void producer(int value){
38+
empty_slots.acquire();//what if there is no empty slots
39+
40+
{
41+
/*
42+
Inside this scope code will run using lock_guard
43+
ans destructed once scope is finished
44+
*/
45+
std::lock_guard<std::mutex> lock(mtx);
46+
buffer.push(value); //as producer keeps on producing, fill the buffer for semaphore to know
47+
std::cout<<"Producing "<<value<<std::endl;
48+
std::cout<<"Buffer after producing: "<<buffer.size()<<std::endl<<std::endl;
49+
}
50+
filled_slots.release(); //signal thta a slot has been filled
51+
}
52+
void consumer(){
53+
filled_slots.acquire();//what if there is no filled slots
54+
int value;
55+
{
56+
/*
57+
Inside this scope code will run using lock_guard
58+
ans destructed once scope is finished
59+
*/
60+
std::lock_guard<std::mutex> lock(mtx);
61+
value = buffer.front();
62+
buffer.pop(); //as producer keeps on producing, fill the buffer for semaphore to know
63+
std::cout<<"Consuming "<<value<<std::endl;
64+
std::cout<<"Buffer after Consuming: "<<buffer.size()<<std::endl<<std::endl;
65+
}
66+
empty_slots.release(); //signal that a slot has been emptied
67+
}
68+
69+
int main(){
70+
std::thread producerThread([]{ //spwan 20 threads
71+
for(int i=1;i<=2000;++i){
72+
producer(i);
73+
}
74+
});
75+
// std::this_thread::sleep_for(std::chrono::milliseconds(10));
76+
std::thread consumerThread([]{
77+
for(int i=1;i<=2000;++i){
78+
consumer();
79+
}
80+
});
81+
producerThread.join();
82+
consumerThread.join();
83+
84+
return 0;
85+
}

processcomm/waitTurn.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include<iostream>
2+
#include<thread>
3+
4+
int turn = 0;
5+
6+
class thread1{
7+
public:
8+
void non_critical_section(){
9+
int a = 0;
10+
while(++a < 10);
11+
}
12+
void operator()(int &x){
13+
while(true){
14+
while(turn != 0); // loop and wait
15+
x += 1;
16+
std::cout<<"Thread 1"<<x<<std::endl;
17+
turn = 1;
18+
non_critical_section();
19+
}
20+
}
21+
};
22+
// this proves that if non_critical_section of a process is large
23+
// it can delay and slow down other process in waitTurn
24+
class thread2{
25+
public:
26+
void non_critical_section(){
27+
int a = 0;
28+
while(++a < 1000000000);
29+
}
30+
void operator()(int &x){
31+
while(true){
32+
while(turn != 1); // loop and wait
33+
x += 1;
34+
std::cout<<"Thread 2"<<x<<std::endl;
35+
turn = 0;
36+
non_critical_section();
37+
}
38+
}
39+
};
40+
int main(){
41+
int x = 0;
42+
thread1 obj1;
43+
thread2 obj2;
44+
std::thread t1(obj1, std::ref(x)); //Process a
45+
std::thread t2(obj2, std::ref(x)); //Process b
46+
47+
t1.join();
48+
t2.join();
49+
50+
return 0;
51+
}

0 commit comments

Comments
 (0)