Saturday, January 20, 2024

The Barrier in C++ 20 concurrency - the programmer in me is still thriving...

Enjoy my training video on the C++ barrier...


The std::barrier class is a synchronization primitive introduced in C++20. It allows a set of threads to synchronize at a certain point in their execution. It is similar to the std::latch class, but it can be reused multiple times.

A std::barrier object is initialized with a count, which specifies the number of threads that must reach the barrier before any of them can proceed. When a thread reaches the barrier, it calls the wait() method. If the count is not yet zero, the thread will be blocked until the count reaches zero. Once the count reaches zero, all of the threads that are waiting on the barrier will be released and can proceed.

The std::barrier class can be used to implement a variety of synchronization patterns, such as producer-consumer queues, parallel algorithms, and race condition prevention.

Here's my application in which I used barrier to showcase how it can be used.

Class Student

/*

* Student.h

*

* Created on: Jan 10, 2024

* Author: som

*/


#ifndef STUDENT_H_

#define STUDENT_H_



#include <iostream>

#include <string>

#include <thread>

#include <barrier>


using namespace std;



class Student {


private:

string name;

int timeLapseBeforeStarting;

int timeToFinish;


public:

Student(string name, int timeLapseBeforeStarting, int timeToFinish){

this->name = name;

this->timeLapseBeforeStarting = timeLapseBeforeStarting;

this->timeToFinish = timeToFinish;


}

virtual ~Student(){


}


void task(barrier<> &b){


this_thread::sleep_for(chrono::milliseconds(timeLapseBeforeStarting));


b.arrive_and_wait();


const auto now = std::chrono::system_clock::now();


const std::time_t t_c = std::chrono::system_clock::to_time_t(now);


cout<< this-> name << " is Starting the task at " << std::ctime(&t_c);


this_thread::sleep_for(chrono::milliseconds(timeToFinish));


cout<< this-> name <<" finished the task"<<endl;


}

};


#endif /* STUDENT_H_ */


Class classETC

/*

* classETC.h

*

* Created on: Jan 10, 2024

* Author: som

*/


#ifndef CLASSETC_H_

#define CLASSETC_H_


#include <thread>

#include <barrier>

#include "Student.h"


using namespace std;


class classETC {


public:

classETC(){


}

virtual ~classETC(){


}


auto giveTaskToStudent(barrier<> &b){

thread riditT(&Student::task, new Student ("Ridit", 1000,2000), ref(b));

thread ishanT(&Student::task, new Student("Ishan", 3000, 1000), ref(b));

thread rajdeepT(&Student::task, new Student("Rajdeep", 900, 1500), ref(b));


riditT.join();

ishanT.join();

rajdeepT.join();

}

};





#endif /* CLASSETC_H_ */



The Main method


//============================================================================

// Name : BarrierC++.cpp

// Author : som

// Version :

// Copyright : som-itsolutions

// Description : Hello World in C++, Ansi-style

//============================================================================


// C++ Program to demonstrate use of use std::barrier in

#include <iostream>

#include <barrier>

#include <thread>


#include "classETC.h"


using namespace std;



int main() {


cout << "C++ Version" << endl; // prints C++ Version

if (__cplusplus == 202101L)

cout << "C++23";

else if(__cplusplus == 202002L)

cout << "C++20\n";

else if (__cplusplus == 201703L)

cout << "C++17\n";

else if (__cplusplus == 201402L)

cout << "C++14\n";

else if (__cplusplus == 201103L)

cout << "C++11\n";

else if (__cplusplus == 199711L)

cout << "C++98\n";

else cout << "pre-standard C++\n";


barrier b ( 3);


classETC etc;


etc.giveTaskToStudent(b);





return 0;

}


The Output:


C++ Version C++20 Ishan is Starting the task at RiditRajdeep is Starting the task at is Starting the task at Sat Jan 20 17:41:30 2024 Sat Jan 20 17:41:30 2024 Sat Jan 20 17:41:30 2024 Ishan finished the task Rajdeep finished the task Ridit finished the task

Have a look at the time when the three different threads are starting - all of them start at the
same time - 17:41:30 - why?
As you have guessed it correctly - it's because of the barrier.
Enjoy...


Friday, January 12, 2024

National Youth Day - here's is a clarion call to the engineers of Bharat - wake up and embrace Sanskrit...

 


Nikola Tesla and Swami Vivekananda

Mr. Toby Grotz, President, Wireless Engineering

Swami Vivekananda, late in the year l895 wrote in a letter to an English friend, "Mr. Tesla thinks he can demonstrate mathematically that force and matter are reducible to potential energy. I am to go and see him next week to get this new mathematical demonstration. In that case, the Vedantic cosmology will be placed on the surest of foundations. I am working a good deal now on the cosmology and eschatology of the Vedanta. I clearly see their perfect union with modern science, and the elucidation of the one will be followed by that of the other." (Complete Works, Vol. V, Fifth Edition, 1347, p. 77).

Here Swamiji uses the terms force and matter for the Sanskrit terms Prana and Akasha. Tesla used the Sanskrit terms and apparently understood them as energy and mass. (In Swamiji's day, as in many dictionaries published in the first half of the present century, force and energy were not always clearly differentiated. Energy is a more proper translation of the Sanskrit term Prana.)

Tesla apparently failed in his effort to show the identity of mass and energy. Apparently, he understood that when speed increases, mass must decrease. He seems to have thought that mass might be "converted" to energy and vice versa, rather than that they were identical in some way, as is pointed out in Einstein's equations. At any rate, Swamiji seems to have sensed where the difficulty lay in joining the maps of European science and Advaita Vedanta and set Tesla to solve the problem. It is apparently in the hope that Tesla would succeed in this that Swamiji says "In that case, the Vedantic cosmology will be placed on the surest of foundations."

Unfortunately, Tesla failed and the solution did not come till ten years later, in a paper by Albert Einstein. But by then Swamiji was gone and the connecting of the maps was delayed.

Engineers of Bharat - don't spend your life as a wage slave.



Reclaim your true identity... 

Embrace #Sanskrit

Read... Read...



Here's why we must declare Sanskrit as the national language of Bharat...


Let's discard Unity in diversity and embrace Unity in Unison - let's all embrace Sanskrit...




Here's my wife Reema reciting her own poem on wisdom


Sunday, January 7, 2024

Latches in C++ 20 concurrency - just like the CountdownLatch of Java concurrency package...

Multithreaded programming is inherently difficult. One of the reasons is that we can't have control over how a thread will start and finish - in which order - it all depends upon the thread scheduling algorithm of the OS. This makes the reproduction of test cases difficult. Moreover, there are race conditions and deadlocks.

When I was teaching the Countdown latch - a thread synchronization technique used in the Java Concurrency package, there was none like that available in C++. I  am happy to see that the concept of latch is introduced in C++20.

So...

What is a Latch in C++?

  • A synchronization primitive was introduced in C++20.
  • It allows one or more threads to wait for a certain number of operations to complete before proceeding.
  • Acts like a countdown counter that blocks threads until it reaches zero.
Good to know that the C++ team is trying to catch up with Java...

Here we go...

My experimentation with C++ latches.




I taught my young son Ridit about the Java Countdown latch three years ago.

Good to see the C++ team is making the standard library more powerful day by day.

Here is the C++ source code of my experimentation.

The following C++ code needs C++20 to compile and execute.



/*

* Student.h

*

* Created on: Jan 7, 2024

* Author: som

*/


#ifndef STUDENT_H_

#define STUDENT_H_


#include <iostream>

#include <string>

#include <thread>

#include <latch>


using namespace std;



class Student {


private:

string name;

int timeToFinish;



public:

Student(string name, int timeToFinish){

this->name = name;

this->timeToFinish = timeToFinish;

}

virtual ~Student(){


}


void task(std::latch& l){


cout<< this->name << " is Starting the task"<<endl;


this_thread::sleep_for(chrono::milliseconds(this->timeToFinish));


cout<< this->name <<" finished the task"<<endl;


l.count_down();

}

};


#endif /* STUDENT_H_ */



/*

* classETC.h

*

* Created on: Jan 7, 2024

* Author: som

*/


#ifndef CLASSETC_H_

#define CLASSETC_H_


#include <thread>

#include <latch>

#include "Student.h"



class classETC {


public:

classETC(){

}

virtual ~classETC(){


}


void giveTaskToStudent(latch& l){

thread riditT(&Student::task, new Student("Ridit", 1000),ref(l));

thread ishanT(&Student::task, new Student("Ishan", 3000), ref(l));

thread rajdeepT(&Student::task, new Student("Rajdeep", 900), ref(l));


cout<<"Teacher is waiting for all the students to finish their task"<<endl;



riditT.join();

ishanT.join();

rajdeepT.join();


l.wait();


cout<<"All students submitted their task... Teacher is leaving the class"<<endl;



}

};


#endif /* CLASSETC_H_ */



Main:


#include <iostream>

#include <latch>

#include <thread>

#include <chrono>


#include "classETC.h"


using namespace std;


int main() {

cout << "C++ Version" << endl; // prints C++ Version

if (__cplusplus == 202101L)

cout << "C++23";

else if(__cplusplus == 202002L)

cout << "C++20\n";

else if (__cplusplus == 201703L)

cout << "C++17\n";

else if (__cplusplus == 201402L)

cout << "C++14\n";

else if (__cplusplus == 201103L)

cout << "C++11\n";

else if (__cplusplus == 199711L)

cout << "C++98\n";

else cout << "pre-standard C++\n";


latch l(3);


classETC etc;

etc.giveTaskToStudent(l);


return 0;

}


Explanation of the code:


Have a look at the Student class. Each student will do his work in a
background thread. As there are 3 students, the latch will be initiated
with 3.

After completing the task, a student will reduce the latch counter by 1.
So when all the students will complete the task, the latch - on which
the main thread was blocked, will become zero and it will unblock the
main thread.

The C++ latches work exactly the way the Java Countdown Latch
works.


For your reference, here's my son Ridit on Java CountdownLatch.


#Enjoy