Multithreaded Sorting with C++Builder and the Parallel Programming Library (PPL)

The Parallel Programming Library (PPL) is one of my favorite features in C++Builder runtime library. PPL allows developers to create tasks that run in parallel to take advantage of multi-core processors.

Using the PPL, you can: 1) speed up loops with a Parallel For, 2) run multiple tasks in parallel using TTask, and 3) use Future Objects to allow a process run with your program focused on other work until the future value is set.

To showcase the TTask feature of the PPL, I’ve created a C++Builder VCL application (build and tested using the C++Builder 10.4 Sydney release) that runs three sort algorithms in separate tasks – Bubble Sort, Shell Sort and the ISO C++ standard Sort (which implements the Quicksort algorithm).

The User Interface

The VCL user interface for my application includes a TButton, two TMemos, and four TLabels. The TButton onClick event handler creates a vector of integers, creates three TTasks (for the sort algorithms) and waits for the sort tasks to complete using the TTask::WaitForAll method.

The Code


#ifndef MainUnitH
#define MainUnitH
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
class TForm1 : public TForm
__published:	// IDE-managed Components
	TButton *Button1;
	TLabel *SortingStatusLabel;
	TLabel *BubbleSortLabel;
	TMemo *Data_Memo;
	TMemo *SortResult_Memo;
	TLabel *ShellSortLabel;
	TLabel *STDSortLabel;
	void __fastcall Button1Click(TObject *Sender);
private:	// User declarations
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
extern PACKAGE TForm1 *Form1;



#include <vcl.h>
#include <System.Threading.hpp>
#include <vector>
#include <algorithm>
#pragma hdrstop

#include "MainUnit.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
void __fastcall TForm1::Button1Click(TObject *Sender)

	_di_ITask My_Tasks[3];
	const int max_data = 15000;   // number of random numbers to create

	int LoopValue = 0;

	Button1->Enabled = false;
	BubbleSortLabel->Caption = "Bubble Sort";
	ShellSortLabel->Caption = "Shell Sort";
	STDSortLabel->Caption = "std::sort";

	SortingStatusLabel->Caption = "Sorting "+IntToStr(max_data)+" integers!";

	// Windows GetTicks() start and stop for each sort method
	int StartBubble,StopBubble;
	int StartShell,StopShell;
	int StartSTD,StopSTD;


	// create a vector of data that all sort algorithms will use
	std::vector<int> my_data;

	// populate the vector with integers
	for (int i = 1; i <= max_data; i++) {
		int random_value = Random(max_data);
		// Data_Memo->Lines->Add(IntToStr(random_value));

	// copy data vector to sort vectors
	std::vector<int> bubble_data = my_data;
	std::vector<int> shell_data = my_data;
	std::vector<int> std_data = my_data;

	// First Task - Bubble Sort
	My_Tasks[0] = TTask::Create([&](){
		// Set Bubble Sort Windows GetTickCount()
		StartBubble = GetTickCount();
		// body of Bubble Sort
		bool swapp = true;
			swapp = false;
			for (size_t i = 0; i < bubble_data.size()-1; i++) {
				if (bubble_data[i]>bubble_data[i+1] ){
					bubble_data[i] += bubble_data[i+1];
					bubble_data[i+1] = bubble_data[i] - bubble_data[i+1];
					bubble_data[i] -=bubble_data[i+1];
					swapp = true;
		// Set the Bubble Sort Stop GetTicks()
		StopBubble = GetTickCount();
	// Start the Bubble Sort Task

	// Second Task - Shell Sort
	My_Tasks[1] = TTask::Create([&](){
		// Set Shell Sort Windows GetTickCount()
		StartShell = GetTickCount();
		// body of the Shell Sort
		for (int gapSize = shell_data.size() / 2; gapSize > 0; gapSize /= 2) {
			for (int currentIndex = gapSize; currentIndex < shell_data.size(); currentIndex++) {
				// save the currentIndex
				int currentIndexCopy = currentIndex;
				// save the value of the currentIndex
				int item = shell_data[currentIndex];
				while (currentIndexCopy >= gapSize && shell_data[currentIndexCopy - gapSize] > item) {
					shell_data[currentIndexCopy] = shell_data[currentIndexCopy - gapSize];
					currentIndexCopy -= gapSize;
				shell_data[currentIndexCopy] = item;
		// Set the Shell Sort Stop GetTicks()
		StopShell = GetTickCount();
	// Start the Shell Sort

	// Third Task - std::sort
	My_Tasks[2] = TTask::Create([&](){
		// Set std::sort Windows GetTickCount()
		StartSTD = GetTickCount();
		// Body of the std::sort
		// Set the std::sort Stop GetTicks()
		StopSTD = GetTickCount();
	// Start the Shell Sort

	// wait until all of the sorting tasks complete
	TTask::WaitForAll(My_Tasks, sizeof(My_Tasks)/sizeof(My_Tasks[0])-1);

	SortingStatusLabel->Caption = "Sorting All done!";

	BubbleSortLabel->Caption = "Bubble Sort Time: "
		+ IntToStr(StopBubble - StartBubble)
		+ " ms";

	ShellSortLabel->Caption = "Shell Sort Time: "
		+ IntToStr(StopShell - StartShell)
		+ " ms";

	STDSortLabel->Caption = "std::sort: "
		+ IntToStr(StopSTD - StartSTD)
		+ " ms";

	// if you want to see the sort results un-comment
	// one of the for loops and the sort result memo statement
	// for(int n : std_data) {
	// for(int n : bubble_data) {
	// for(int n : shell_data) {
		// SortResult_Memo->Lines->Add(IntToStr(n));
	// }

	// clear the vectors

	Button1->Enabled = true;

The form after sorting 15,000 integers


PPL – Parallel Programming Library –

Using TTask –

Using TParallel::For –

Using TTask::IFuture –

Algorithms Library –

std::sort –

C++Builder Product Information

C++Builder Product Page – Native Apps that Perform. Build Windows C++ Apps 10x Faster with Less Code
C++Builder Product Editions – C++Builder is available in four editions – Professional, Enterprise, Architect and Community (free). C++Builder is also available as part of the RAD Studio development suite.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s