Semaphores in C++
In this tutorial, we will learn about semaphore in C++. We will also see a sample code to understand it better.
What is a semaphore?
A semaphore is a non-negative variable which can be used to access a common resource of the operating system.
Semaphores are used to overcome the critical section problem. The critical section is an area in a program that is used to access common resources. But, two programs cannot enter the critical section simultaneously Semaphores come in handy in such situations.
Types of semaphores in C++:
There are two types of semaphores:
- Binary semaphores: As the name suggests, a binary semaphore can take only two values, 0 and 1. The default value of a binary semaphore is 1. It is also known as a mutex lock.
- Counting semaphores: These have values which may range from 0 to any number ‘n’. They have an unrestricted domain.
Operations on semaphores in C++
Semaphores solve the critical section problem by using two atomic operations, wait() and signal().
wait operation: if the value of the semaphore s is negative or zero, no operation is performed. If the value of s is positive, it is decremented. The pseudocode for wait operation is as follows:
wait(s) { while(s<=0); s--; }
signal operation: This operation is used to increase the value of the semaphore s. The pseudocode for signal operation is as follows:
signal(s) { s++ }
Sample code for implementing semaphore in C++:
The following code can be used to effectively implement and understand semaphores in C++:
#include<iostream> #include<mutex> using namespace std; struct semaphore { int mutex; int rcount; int rwait; bool wrt; }; void addR(struct semaphore *s) { if(s->mutex == 0 && s->rcount == 0) { cout<<"\nSorry, File open in Write mode.\nNew Reader added to queue.\n"; s->rwait++; } else { cout<<"\nReader Process added.\n"; s->rcount++; s->mutex--; } return ; } void addW(struct semaphore *s) { if(s->mutex==1) { s->mutex--; s->wrt=1; cout<<"\nWriter Process added.\n"; } else if(s->wrt) cout<<"\nSorry, Writer already operational.\n"; else cout<<"\nSorry, File open in Read mode.\n"; return ; } void remR(struct semaphore *s) { if(s->rcount == 0) cout<<"\nNo readers to remove.\n"; else { cout<<"\nReader Removed.\n"; s->rcount--; s->mutex++; } return ; } void remW(struct semaphore *s) { if(s->wrt==0) cout<<"\nNo Writer to Remove\n"; else { cout<<"\nWriter Removed\n"; s->mutex++; s->wrt=0; if(s->rwait!=0) { s->mutex-=s->rwait; s->rcount=s->rwait; s->rwait=0; cout<<"waiting Readers Added:"<<s->rcount<<endl; } } } int main() { struct semaphore S1={1,0,0}; while(1) { cout<<"Options :-\n1.Add Reader.\n2.Add Writer.\n3.Remove Reader.\n4.Remove Writer.\n5.Exit.\n\n\tChoice : "; int ch; cin>>ch; switch(ch) { case 1: addR(&S1); break; case 2: addW(&S1); break; case 3: remR(&S1); break; case 4: remW(&S1); break; case 5: cout<<"\n\tGoodBye!";break; default: cout<<"\nInvalid Entry!"; } } return 0; }
The above-given code implements the reader-writer problem using semaphores. The output of the code will look something like this:
Options :- 1.Add Reader. 2.Add Writer. 3.Remove Reader. 4.Remove Writer. 5.Exit. Choice : 1 Reader Process added. Options :- 1.Add Reader. 2.Add Writer. 3.Remove Reader. 4.Remove Writer. 5.Exit. Choice : 1 Reader Process added. Options :- 1.Add Reader. 2.Add Writer. 3.Remove Reader. 4.Remove Writer. 5.Exit. Choice : 1 Reader Process added. Options :- 1.Add Reader. 2.Add Writer. 3.Remove Reader. 4.Remove Writer. 5.Exit. Choice : 3 Reader Removed. Options :- 1.Add Reader. 2.Add Writer. 3.Remove Reader. 4.Remove Writer. 5.Exit. Choice : 2 Sorry, File open in Read mode. Options :- 1.Add Reader. 2.Add Writer. 3.Remove Reader. 4.Remove Writer. 5.Exit. Choice : 3 Reader Removed. Options :- 1.Add Reader. 2.Add Writer. 3.Remove Reader. 4.Remove Writer. 5.Exit.
With this, we come to the end of this tutorial.
Also read:
Leave a Reply