Tuesday, March 15, 2016

A worker thread in C++

Introduction

Sometimes we need an extra thread to do a task for us in parallel or to just unblock main thread. For better performance we would not like to create a new thread every time, Also we need little more control over the thread. In this article, we will implement a thread with below abilities.
  • Submit a task to be executed asynchronously
  • Submit a task to be executed synchronously ( but on worker thread)
  • Automatically wait for task to complete 
  • Implementation uses C++ 11 extensively ( thread , lambda , condition variables)

Using the code

Below sample code list usages of worker thread
#include <iostream>
#include <chrono>
#include <thread>
#include "workerthread.h"

int main()
{
    std::cout << "Hi, Welcome to demo of worker thread" << std::endl;

    {
        // Create two worker threads
        WorkerThread thread;
        WorkerThread thread2;

        // Example of a synchronous task
        thread.doSync([]{    std::cout << "First - blocking call" << std::endl;    });

        for (int i = 1; i < 100; i++)
        {
            auto& t = i % 2 == 0 ? thread : thread2;
            if (i == 10) // Another synchronous task in between
            {
                thread.doSync([]{    std::cout << "Second - blocking call" << std::endl;    });
            }
            // Multiple asynchronous tasks queued
            t.doAsync([i]
            {
                std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(200));
                std::cout << (i % 2 == 0 ? "thread-" : "thread2-") << "iteration number: " << i <<                std::endl;
            });
        }
    
        thread.doSync([]{    std::cout << "Last - blocking call";    });
    }// Added extra scope to demo destruction of worker thread
    std::cout << "This must be last line\n";

}

Implementation of worker thread
  • Use C++ function construct to store submitted task
  • Finish the present queue and wait for signal for new work
void WorkerThread::startThread()
{
    std::unique_lock<std::mutex> l(mutex);
    do
    {
        while (isRunning && tasks.empty())
            itemInQueue.wait(l);

        while (!tasks.empty())
        {
            auto size = tasks.size();
            printf("Number of pending task are %d\n", size);
            const std::function<void()> t = tasks.front();
            tasks.pop_front();
            l.unlock();
            t();
            l.lock();
        }
        itemInQueue.notify_all();

    } while (isRunning);
    itemInQueue.notify_all();
}

An asynchronous task is just queued and calling thread not blocked
void WorkerThread::doAsync(const std::function<void()>& t)
{
    std::lock_guard<std::mutex> _(mutex);
    tasks.push_back(t);
    itemInQueue.notify_one();

}
 Synchronous task is little trickier, We need to block calling thread until all task queued before the submitted task and submitted task completes.

void WorkerThread::doSync(const std::function<void()>& t)
{
    std::condition_variable event;
    bool finished = false;

    std::unique_lock<std::mutex> l(mutex);
    auto lambda = [this, &t, &finished, &event]
    {
        t();
        std::lock_guard<std::mutex> l(mutex);

        finished = true;
        event.notify_one();
    };
    tasks.push_back(lambda);
    itemInQueue.notify_one();

    while (!finished)
        event.wait(l);

}

Next update

- Implement priority of task
- Allow cancellation of task

Sunday, March 13, 2016

Starting Test Driven Development [TDD]

For a serious developer, Test drive development is a must. It will save you from many difficult situations.
In this blog, we will see how to use Google Test framework for c++.

There could be two ways to include google test framework in your project.

  • Download google test framework from GitHub, Build it and use it
  • Use NuGet Package Manger in visual studio to install and use it

Starting with google test. A simple example

#include <iostream>
#include <gtest\gtest.h> // This file is required for google test


// Test Fixuture class
class TestAirthmatic:public testing::Test
{
public:
virtual void SetUp()override {}
virtual void TearDown()override {}
int add(int aint b) { return a + b; }
int divide(const int valconst int by)
{
return val / by;
}
};

// Writing test case
TEST_F(TestAirthmatic, Demo_passCase) { EXPECT_EQ(4, add(2, 2)); }// A demo test which will pass
TEST_F(TestAirthmatic, Demo_FailCase) { EXPECT_EQ(4, add(3, 2)); }// A demo test which will fail
TEST_F(TestAirthmatic, DISABLED_test) {} // A disabled test case

int main(int argcchar** argv)
{
testing::InitGoogleTest(&argcargv);
return RUN_ALL_TESTS();
}

Output of Test is





Saturday, March 12, 2016

When microseconds matter, Measure it

/*
You write a great code! But it is still wise that you keep measuring how it performs, You shall write test case to keep measuring time taken by API in high precision.

In this blog, I will explain how to use Query performance counter windows API to measure the time taken by your API with high precision.




The QueryPerformanceCounter and QueryPerformanceFrequency API
This API is backed by a virtual counter running at a "fixed" frequency started at boot time.
The following two basic calls are used to explore the microsecond regime : QueryPerformanceCounter() and QueryPerformanceFrequency().The counter values are derived from some hardware counter, which is platform dependent.However, the Windows version also influences the results by handling the counter in a version specific manner.Windows 7, particular has introduced a new way of supplying performance counter values.

QueryPerformanceCounter
The call to BOOL QueryPerformanceCounter(OUT LARGE_INTEGER *lpPerformanceCount); will update the content of the LARGE_INTEGER structure PerformanceCount with a count value. The count value is initialized to zero at boot time.

QueryPerformanceFrequency
The call to BOOL QueryPerformanceFrequency(OUT LARGE_INTEGER *lpFrequency); will update the content of the LARGE_INTEGER structure PerformanceFrequency with a frequency value. 
*/

#include <Windows.h>
#include <iostream>
#include <vector>
#include <list>



class QueryPerformanceCounterC
{
public:
QueryPerformanceCounterC() :PCFreq(0.0), CounterStart(0){}
void start()
{
LARGE_INTEGER li;
/*
Retrieves the frequency of the performance counter. The frequency of the performance counter is fixed at system boot and is consistent across all processors. Therefore, the frequency need only be queried upon application initialization, and the result can be cached.
*/
if (!QueryPerformanceFrequency(&li))
throw "QueryPerformanceFrequency failed!\n";

PCFreq = double(li.QuadPart) / 1000.0;
/*
Retrieves the current value of the performance counter,
which is a high resolution (<1us) time stamp that can be used for time-interval measurements.
*/
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;

}

double stop()
{
LARGE_INTEGER li;

/*
Retrieves the current value of the performance counter, which is a high resolution (<1us) time stamp that can be used for time-interval measurements.
*/
QueryPerformanceCounter(&li);
return double(li.QuadPart - CounterStart) / PCFreq;

}

private:
double PCFreq;
__int64 CounterStart = 0;

};


int main()
{

// A simple example, You have values in List, You API need it in Vector
// There are two version of coping
std::list<int> from;
from.resize(1000); // Input list

std::vector<int> one; // Destination one
std::vector<int> two; // Destination two

QueryPerformanceCounterC counter;
counter.start();
for (auto const& a : from) // Case 1: Push Back one by one
one.push_back(a);
std::cout << counter.stop() << std::endl;


QueryPerformanceCounterC counter2;
counter2.start();
two.resize(from.size()); // <- This single line will improve performance
for (auto const& a : from) // Case 2: Same as Case 1, But you allocate memory in advance
two.push_back(a);
std::cout << counter2.stop() << std::endl;
}