• Top
  • Reply

My attempt on threading

Disclaimer: If you are using threads in serious projects look at boost::threads or std::thread, the following is just a little test so use if you want but you have been warned

The Dashee project required me to implement threading so tasks such as reading from the sensor or reading from the server could be threaded. Now I know the actual Pi is single core but it still can take advantage of threads in its main loop sleep time.

To do the Thread class I decided to encapsulate the pthread_ API in it's own little class wrapper. Im not going to go in detail of the source code of the wrapper but the following examples shows the usage.

For example sakes, we assume all programs are compiled with -ldashee using libdashee.so from the Dashee project and -pthread for pthreads to work. We also imply that include <iostream> is above every example.

Using a simple thread

Lets start simple, lets get a thread to add 1 to a passed variable 100 times, so at the end of the thread the value of parameter value will be value + 100

#include <dashee/Threads/Thread.h>

void * doWork(void * v)
{
    for (int i = 0; i < 100; i++)
    {
          (*v)++;
    }
}

int main()
{
    int x = 0
    dashee::Threads::Thread t1(doWork);
    t1.start(static_cast<void *>(&x));
    t1.join();
    std::cout << "Value of x: " << x << std::endl;

    return 0;
 }

Working with Locks

A threading class would not be complete without locking. The Dashee interface provides an encapsulation of locking.

#include <dashee/Threads/Thread.h>
#include <dashee/Threads/Lock/Mutex.h>

dashee::Threads::Lock * l1;

void * doWork(void * v)
{
    for (int i = 0; i < 100; i++)
    {
          li->lock();
          (*v)++;
          li->unlock();
    }
}

int main()
{
    int x = 0;        
    l1 = new dashee::Threads::LockMutex();

    dashee::Threads::Thread t1(doWork);
    dashee::Threads::Thread t2(doWork);

    t1.start(static_cast<void *>(&x));
    t2.start(static_cast<void *>(&x));

    t1.join();
    t2.join();

    // Prints 200
    std::cout << "Value of x: " << x << std::endl;

    delete l1;
    return 0;
 }

Lock safety using RAII

What happens if your inner loop throws an exception your thread will lock for ever. You can try putting an unlock in each catch block (There is no finally concept in C++) but that is messy. So what we can do is use RAII concept implemented in our Scope class. Because a destructor of an initialized object is called at the end of a scope.

We can use this concept to unlock the lock as soon as it gets to the end of the scope or an exception is thrown.

#include <dashee/Threads/Thread.h>
#include <dashee/Threads/Scope.h>
#include <dashee/Threads/Lock/Mutex.h>

dashee::Threads::Lock * l1;

void * doWork(void * v)
{
    for (int i = 0; i < 100; i++)
    {
          dashee::Threads::Scope s1(l1);
          (*v)++;
          // s1 destructor is called, which calls unlock of l1 :D
    }

    dashee::Threads::Thread::exit();
    return NULL;
}

int main()
{
    int x = 0;        
    l1 = new dashee::Threads::LockMutex();

    dashee::Threads::Thread t1(doWork);
    dashee::Threads::Thread t2(doWork);

    t1.start(static_cast<void *>(&x));
    t2.start(static_cast<void *>(&x));

    t1.join();
    t2.join();

    // Prints 200
    std::cout << "Value of x: " << x << std::endl;

    delete l1;
    return 0;
 }

Not only we have lock safety but a little more cleaner code. Also if you look closely the doWork function calls the exit static function, which is also the part of the dashee Thread interface.

Read and Write locks

You can also use read and write locks by using the following syntax:

dashee::Threads::LockReadWrite l1;
l1.lock(dashee::Threads::Lock::LOCKTYPE_READ)
l1.unlock();
l1.lock(dashee::Threads::Lock::LOCKTYPE_DEFAULT) // Same as li.lock();
l1.unlock();

Try playing around with it, download the source code and plug the library in the above examples.

Post if you find improvements. Or comment if you need help

By

8th Dec 2013
© 2011 Shahmir Javaid - http://shahmirj.com/blog/35


Back to Top
All content is © copyrighted, unless stated otherwise.
Subscribe, @shahmirj, Shahmir Javaid+