![Barcode For FMX | Embarcadero RAD Studio Delphi C++Builder Blogs](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/Barcode-For-FMX-1.jpg?resize=1024%2C694&ssl=1)
C++ Builder provides three levels of development:
1. Components (VCL and FMX)
2. Common Libraries (RTL).
3. Platform APIs (iOS, Android, Mac OS)
In this post we will discuss the Common Libraries (RTL).
C++ Builder has several hundred functions, macros, and classes that you call from within your C and C++ programs to perform a wide variety of tasks, including low- and high-level I/O, string and file manipulation, memory allocation, process control, data conversion, mathematical calculations, and more.
The C++ Builder Run-Time Library (or RTL) is composed of a number of base header files that provide the underlying support for most of the VCL and FireMonkey component libraries . The RTL includes global routines, utility classes such as those that represent streams and lists, and classes such as TObject, TPersistent, and TComponent.
Although closely allied with FireMonkey and VCL, the RTL does not include any of the components that appear on the Tool Palette.
Instead, the classes and routines in the RTL are used by the components that do appear on the Tool Palette, and are available for you to use in application code in either VCL projects or FireMonkey projects, or when you are writing your own classes.
For example, the System header contains most of the Run-Time Library (RTL).
And from the System header, you have the System.Math.hpp header that defines classes, routines, types, variables, and constants related to mathematical operations, vectors and matrices.
Or the System.Bluetooth.hpp header that provides classes to use the Bluetooth capabilities of the device that is running your application to connect to applications running on remote devices.
Or the System.Sensors.hpp header that provides classes and components that let you obtain information and manage system sensors. The Sensors are pieces of hardware or software that can provide measures of physical quantities to your applications.
Or the System.Threading.hpp header that defines classes and types that implement the parallel programming library.
Let’s now look at a C++ Builder example using System.Threading.hpp header and the Parallel Programming Library.
For my example application, I’ll be using a C++ Builder 10.4 project application that uses a Common Run Time Library, in a Multi-Device Application, using the RTL’s System.Threading header and the Parallel Programming Library.
You can download this sample TParallelPrime.cbproj project application here.
![UI | Embarcadero RAD Studio Delphi C++Builder Blogs](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/UI.jpg?resize=642%2C234&ssl=1)
Here is a C++ Builder project application that uses a Common Run Time Library, in a Multi-Device Application, using the RTL’s System.Threading header and the Parallel Programming Library.
1 2 3 |
#include <System.Threading.hpp> // TParallel::For #include <System.Diagnostics.hpp> // System::Diagnostics::TStopwatch #include <System.SyncObjs.hpp> // TInterlocked::Increment |
This example shows how to use the TParallel.For method from the Parallel Programming Library (PPL). TParallel.For splits a for loop into pieces that run in parallel and uses tasks to run those pieces.
This application finds the number of prime numbers, between 1 and a MAX value, like 5 million in this application. The application will calculate the time to do this using (1) the classic for loop and we will do the same using the parallel version using the TParallel.For method.
On the applications UI:
The “For Loop” button will launch the serial version of the prime numbers calculation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Button event handler that finds prime numbers using the classic for loop void __fastcall TForm2::btnForLoopClick(TObject *Sender) { int Max = 5000000; // 5 Million Tot = 0; System::Diagnostics::TStopwatch sw = System::Diagnostics::TStopwatch::Create(); sw.Start(); for (int I = 1; I <= Max; I++) { if (IsPrime(I)) { Tot++; } } sw.Stop(); Memo1->Lines->Add (String().sprintf (L"Sequential For loop. Time (in milliseconds): %lld, Primes found: %lld", sw.ElapsedMilliseconds, Tot)); } |
The “Parallel Loop” button will launch the parallel version of the prime numbers calculation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Button event handler that finds prime numbers using the Parallel::For method void __fastcall TForm2::btnParallelLoopClick(TObject *Sender) { int Max = 5000000; // 5 Million Tot = 0; System::Diagnostics::TStopwatch sw = System::Diagnostics::TStopwatch::Create(); sw.Start(); // In C++, the IsPrime function passes to the TParallel.For as an Iterator Event. TParallel::For(NULL, 1, Max, MyIteratorEvent); // Second option is to use a C++11 Lambda for the Parallel::For /* TParallel::For(NULL, 1, Max, System::Sysutils::_di_TProc__1<int>( // [this] (int AIndex) { [&](int AIndex) { if (IsPrime(AIndex)) {TInterlocked::Increment(Tot);};})); */ sw.Stop(); Memo1->Lines->Add (String().sprintf (L"Parallel For loop. Time (in milliseconds): %lld, Primes found: %lld", sw.ElapsedMilliseconds, Tot)); } |
The Memo box displays the calculation times between the classic for loop for (int I = 1; I <= Max; I++) and the parallel for loop version using the TParallel::For method:
![Memo | Embarcadero RAD Studio Delphi C++Builder Blogs](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/Memo.jpg?resize=474%2C53&ssl=1)
As we can see from the calculations, it took the serial For Loop 814 milliseconds to calculate the number of Prime numbers between 1 and 5 Million, but it only tooks 267 milliseconds to do the same using the TParallel::For method. It’s clear that the TParallel::For method is more efficient, and runs the application much faster, since it makes use of the available CPU’s for running procedures in parallel. The Virtual Machine I used for my Windows partition, is using 4 processor cores, so we see by using the TParallel::For method , the application runs basically 4 times faster! The more cores you have the faster your application will run using the TParallel::For method!
Looking at the code, we see how we implemented this application.
If you cursor over the #include <System.Threading.hpp> | Right-Click | Open File at Cursor, you will open your C:\Program Files (x86)\Embarcadero\Studio\21.0\include\windows\rtl\System.Threading.hpp file.
Then using Methods Insight | search for For.
![For | Embarcadero RAD Studio Delphi C++Builder Blogs](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2020/08/For.jpg?resize=556%2C262&ssl=1)
We see we have 43 methods for using TParallel.For.
Looking at the first one, we see in this System.Threading.TParallel.For header, it includes a number of overloaded arguments to make it very suitable for C++ development!
The Parallel Programming Library (PPL) includes this loop function, TParallel::For, that allows to run its loops in parallel!
And for all this, there is a Thread Pool that self tunes itself automatically (based on the load on the CPU’s) so you do not have to care about creating or managing threads for this purpose!
To use the Parallel Programming Library in your application just including System.Threading header. This header has several features that can be included into new and existing C++ Builder projects.
Going back into the applications UI, when we click on the For Loop button, we see we are using the regular serial For Loop function, and we check if our number from 1 to 5 million is a Prime number.
To check if the number is a Prime Number, we use this function in our application:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
bool __fastcall TForm2::IsPrime(int N) { int Test, k; bool aPrime; if (N <= 3) { return N > 1; } else if (((N % 2) == 0) || ((N % 3) == 0)) { return false; } else { aPrime = true; k = (int)sqrt(N); Test = 5; while (Test <= k) { if (((N % Test) == 0) || ((N % (Test + 2)) == 0)) { aPrime = false; break; // jump out of the for loop } Test = Test + 6; } return aPrime; } } |
Next, when we click on the Parallel Loop button, we see we are using the RTL’s TParallel::For method. And in C++ our IsPrime function needs to be passed to the TParallel.For method as either an Iterator Event, or as a C++11 Lambda.
For the Iterator Event, here is how we implemented the IsPrime function as an Iterator Event:
1 2 3 4 5 6 7 8 9 10 11 12 |
// Parallel For Iterator Event Proc void __fastcall TForm2::MyIteratorEvent(TObject* Sender, int AIndex) { // The Iterator Event implementation code is as follows. // In C++ you create an Iterator event function or C++11 lambda and // pass that as part of the TParallel::For loop call. // // Within parallel loops, you must transform your operations into thread-safe operations. // Here we use a member of the RTL System.SyncObjs header, the TInterlocked method. if (IsPrime(AIndex)) { TInterlocked::Increment(Tot); } } |
The second option, for our C++ IsPrime function to be passed to the TParallel.For method, is to use a C++11 Lambda for the Parallel::For, as we see here in the code. Here we see our Lambda Expression: [&](int AIndex) . This captures our variable by ref.
1 2 3 4 5 |
// Second option is to use a C++11 Lambda for the Parallel::For TParallel::For(NULL, 1, Max, System::Sysutils::_di_TProc__1<int>( // [this] (int AIndex) { [&](int AIndex) { if (IsPrime(AIndex)) {TInterlocked::Increment(Tot);};})); |
If you run the same application using the Lambda code, you will get the same results.
From running the application , we saw how the TParallel::For is more efficient since it makes use of the available CPUs for running procedures in parallel. And this application also shows C++ 11 support in C++ Builder, including support for Lambda Expressions!
In conclusion, the C++ Builder RTL includes a Parallel Programming Library (PPL).
One great use of the PPL, is to make looping faster, by using the TParallel.For method.
The PPL, part of C++ Builder RTL, in the System.Threading header also gives your applications the ability to have tasks running in parallel taking advantage of working across multiple CPU devices and computers. The PPL includes a number of advanced features for running tasks, joining tasks, waiting on groups of tasks, as well as the TParallel::For method we just saw in this application.
Some additional useful references:
Using the RTL (Run-Time Library)
Tutorial: Using the For Loop from the Parallel Programming Library
Video: How to use the Parallel Prime for C++ Builder VCL.
Download Your Free 30 day C++Builder Trial Today from this link
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition