Search in the blog

вівторок, 23 листопада 2010 р.

Here is "False sharing" example, you can try it in VS with enabled OpenMP flag. Also if you enable speed optimization for compiler single thread version will be faster, but you can see false sharing effect too.

#include <iostream>
#include <ctime>
#include <omp.h>

using std::cout;
using std::endl;

const double M=8e8;

//single thread work to do
void one_thread() 
{
    long int n1=1, n2=1;
    for(; n1<M; n1+=n1%3);
    for(; n2<M; n2+=n2%3);
    cout << "Sum = " << n1 + n2 << endl;
}


//multi thread work to do
void multi_thread() 
{
    struct T
    {
        long int n1;
        char chuck[64];//should be commented to see false sharing effect
        long int n2;
    } t;
    t.n1 = 1;
    t.n2 = 1;
    #pragma omp parallel num_threads(2) shared(M,t)
    {
        #pragma omp sections
        {
            #pragma omp section
            for(; t.n1<M; t.n1+=t.n1%3);

            #pragma omp section
            for(; t.n2<M; t.n2+=t.n2%3);
        }
    }
    cout << "Sum = " << t.n1 + t.n2 << endl;
}

time_t start, end;
double diff;

int main(int argc, char* argv[]) 
{
    time(&start);
    multi_thread();
    time(&end);
    diff=difftime(end, start);
    cout<<diff<<" seconds elapsed for multi thread calculation."<<endl;

    time(&start);
    one_thread();
    time(&end);
    diff=difftime(end, start);
    cout<<diff<<" seconds elapsed for 1 thread calculation."<<endl;
    return 0;
}

четвер, 12 серпня 2010 р.

Again about rvalues

You can use rvalues for creating move semantics - remove copy constructors for temporaries. Example:

#include <iostream>

class A
{
public:
    A()
    {
        x = new int[1];
        x[0] = 1;
        std::cout << "new\n";
    }
    ~A()
    {
        delete[] x;
    }

    A(const A& a)
    {
        x = new int[1];
        x[0] = a.x[0];
        std::cout << "new\n";
    }

   /* A(A&& a) //move constructor
    {
        x = a.x;
        a.x = 0;
    }*/
private:
    int *x;
};

A GetA()
{
    A a;
    return a;
}

//if you want to use movable object as member in another object you should declare move constructor
//and use std::move
class B
{
public:
    B(){}
    B(B&& b) //move constructor
    {
        a = std::move(b.a);
    }
    A a;
};

B GetB()
{
    B b;
    return b;
}

int main(int, char*[])
{
    B b = GetB();
    {
        A a = GetA();
        A a2(a);
        std::cout << "scope\n";
    }
    return 0;
}

понеділок, 7 червня 2010 р.

New web page

I have updated my personal page. You can find updated demo section there.

четвер, 3 червня 2010 р.

C++0x multi-threading

If you want to play with new functionality for multi-threading in C++ for free you need gcc-4.5 and Linux, MinGW currently doesn't support this functionality (but it has all required headers). To compile programm you need to specify complier flag -std=c++0x and linker flag -pthread. VC++ currently have not this functionality too. Here is small example:

#include <thread>
#include <mutex>
#include <iostream>
#include <unistd.h>

class MyJob
{
public:
    MyJob(std::mutex* m) : m(m){}
    void operator()()
    {
        for (int i = 0; i < 5; ++i)
        {
            {
                std::lock_guard<std::mutex> lock(*m);
                std::thread::id id = std::this_thread::get_id();
                std::cout << "Thread " << id << std::endl;
            }
            sleep(1);
        }
    }
private:
    std::mutex* m;
};

int main()
{
    std::mutex m;
    std::thread t1{MyJob(&m)};
    std::thread t2{MyJob(&m)};

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

    return 0;
}

четвер, 13 травня 2010 р.

FLTK Fluid horisontal widgets

If you want to make some widget in FLTK horizontal you have to go to the c++ properties:

вівторок, 27 квітня 2010 р.

CMake + VC++2010

There is now the bug in CMake 2.8.1 with Visual Studio 2010 Express - compiler checks doesn't work. Here is http://www.itk.org/Bug/view.php?id=10539 patch for this bug.

вівторок, 20 квітня 2010 р.

Time convertions with daylight saving

I've found how to convert time from UTC to local time with daylight saving correction:
1. Use mktime() to create time from string(or some thing else)
2. get time from gmtime() and localtime()
3. calculate difference between time to get timezone offset (or use _get_timezone)
4. use tm::tm_isdst to determine apply or not daylight saving
5. use _get_daylight() to get value in hours of daylight correction.

понеділок, 19 квітня 2010 р.

Online compiler

Here is codepad cool on-line compiler

неділя, 18 квітня 2010 р.

Perfect forwarding full example

Here is an example of how to use rvalue references for forwarding:

#include <functional>
#include <iostream>
#include <memory>

class V
{
public:
    explicit V(int x)
        :x(x)
    {
            std::cout << "V()\n";
    }

    int x;
protected:
    V(const V&){}
    V& operator=(const V&){}
};

class A
{
public:
    A(V& v)
    {
        std::cout << "A(V&) x = " << v.x << "\n";
    }
};

template<typename T, typename Arg> 
std::shared_ptr<T> factory(Arg arg)
{ 
  return std::shared_ptr<T>(new T(arg));
} 

template<typename T, typename Arg> 
std::shared_ptr<T> factory2(Arg&& arg)
{ 
    // you can't use std::move for forwarding - compiler error
    return std::shared_ptr<T>(new T(std::forward<V>(arg)));
} 

int main(int argc, char* argv[])
{  
    V v(1);

    A a(v);

    // compiler error
    //std::shared_ptr<A> a1 = factory<A>(v);

    std::shared_ptr<A> a1 = factory2<A>(v);

    return 0;
}

Practical example of Rvalue references and move semantics

Here is simple example how to use move semantics to optimize you code - you can override + operator to reduce constructor numbers:
#include <functional>
#include <iostream>

class A
{
public:
    A(int x)
        :x(x)
    {
        std::cout << "A(int x)\n";
    }

    A(const A& a)
        :x(a.x)
    {        
        std::cout << "A(const A&)\n";
    }

    A& operator=(const A& a)
    {
        x = a.x;
        return *this;
    }

    A operator+(const A& a)
    {
        return A(x + a.x);
    }

private:
    int x;
};


class B
{
public:
    B(int x)
        :x(x)
    {
        std::cout << "B(int x)\n";
    }

    B(const B& b)
        :x(b.x)
    {        
        std::cout << "B(const B&)\n";
    }

    B(B&& b)
        :x(std::move(b.x))
    {        
        std::cout << "B(B&&)\n";
    }

    B& operator=(const B& b)
    {
        x = b.x;
        return *this;
    }

    B& operator=(B&& b)
    {
        x = std::move(b.x);
        return *this;
    }

    B operator+(const B& b)
    {
        return B(x + b.x);
    }

    B&& operator+(B&& b)
    {
        b.x += x;
        return std::move(b);
    }

private:
    int x;
};
 
int main(int argc, char* argv[])
{
    A a1(5);
    A a2 = a1 + 2 + 3;

    B b1(5);
    B b2 = b1 + 2 + 3;
    return 0;
}

пʼятниця, 16 квітня 2010 р.

Simple unit test framework for C++

I want to create very simple unit test framework for C++ which can be used with Visual Studio. I mean that it must have some integration to IDE. When i searched  for some existent frameworks i didn't find anything useful and open source. Also i want this framework should be very lightweight, and test creation should take very little time, because instead test creation doesn't have sense.
So here is first version, it use new features from C++0x, and was created in Visual Studio2010 Express.It produce output to standard Output window, and you can click on failed assertion message to move you code editor to required code line.

Test.h:

#pragma once 

#include <sstream>

#define CHECK(v) self->Assert(##v, L#v, __FILE__, __LINE__);

#define CHECK_EQUALS(v1, v2) self->AssertEquals(##v1, ##v2, L#v1,  L#v2, __FILE__, __LINE__);

#define CHECK_NOT_EQUALS(v1, v2) self->AssertNotEquals(##v1, ##v2, L#v1,  L#v2, __FILE__, __LINE__);

#define TEST(name) void name(testengine::Test* self)

namespace testengine
{

class Test
{
public:
    Test() : done(true) {self = this;}
    virtual ~Test(){}
    virtual void Setup(){}
    virtual void TearDown(){}
    virtual void Run() = 0;   

    void Assert(bool rez, const std::wstring& msg, const std::string& fileName, size_t line)
    {
        if (!rez)
        {
            std::wstringstream buf;        
            buf << fileName.c_str() << L"(" << line << ") : Assertation failed : " << msg.c_str() << std::endl;
            report += buf.str();
            done = false;
        }    
    }

    template <class T1, class T2>
    void AssertEquals(T1 v1, T2 v2, const std::wstring& msg1, const std::wstring& msg2, const std::string& fileName, size_t line)
    {
        std::wstringstream buf;
        buf << msg1 << L" == " << msg2;
        Assert(v1 == v2, buf.str(), fileName, line);
    }

    template <class T1, class T2>
    void AssertNotEquals(T1 v1, T2 v2, const std::wstring& msg1, const std::wstring& msg2, const std::string& fileName, size_t line)
    {
        std::wstringstream buf;
        buf << msg1 << L" != " << msg2;
        Assert(v1 != v2, buf.str(), fileName, line);
    }

    const std::wstring GetReport() {return report;}

    bool IsDone() {return done;}
protected:
    Test* self;
private:    
    std::wstring report;
    bool done;
};

}

TestExecuter.h:

#pragma once 

#include "Test.h"

#include <memory>
#include <vector>
#include <string>
#include <tuple>
#include <sstream>
#include <functional>

#include <windows.h>

namespace testengine
{

typedef std::function<void(Test*)> TestFunction;

class SingleFunctionTest : public Test
{
public:
    SingleFunctionTest(TestFunction func) : func(func){}
    virtual void Run()
    {
        func(this);
    }

private:
    TestFunction func;
};

class TestExecuter
{
public:

    void AddTest(TestFunction func, const std::wstring& name)
    {
        tests.push_back(std::make_tuple(name, new SingleFunctionTest(func))); 
    }

    template<class T>
    void AddTest(const std::wstring& name)
    {
        tests.push_back(std::make_tuple(name, new T)); 
    }

    void RunTests()
    {
        OutputDebugStringW(L"=============================================================================\n");
        OutputDebugStringW(L"Start running tests :\n");
        auto i = tests.begin(), e = tests.end();
        size_t passed = 0;
        size_t failed = 0;
        for (;i != e; ++i)
        {
            OutputDebugStringW(L"-----------------------------------------------------------------------------\n");
            bool go = true;
            std::wstringstream buf;
            buf << std::get<0>(*i);
            try
            {
                std::get<1>(*i)->Setup();               
            }
            catch(...)
            {
                buf << L" - Fails : Unhandled exception while Setup\n";
                OutputDebugStringW(buf.str().c_str());
                go = false;
                ++failed;
            }

            if (go)
            {
                try
                {
                    std::get<1>(*i)->Run();               
                }
                catch(...)
                {
                    buf << L" - Fails : Unhandled exception while Run\n";
                    OutputDebugStringW(buf.str().c_str());
                    go = false;
                    ++failed;
                }
            }

            if (go)
            {               
                try
                {
                    std::get<1>(*i)->TearDown();               
                }
                catch(...)
                {
                    buf << L" - Fails : \n";
                    buf << std::get<1>(*i)->GetReport();
                    buf << L"Unhandled exception while TearDown\n";
                    OutputDebugStringW(buf.str().c_str());
                    go = false;
                    ++failed;
                }
            }

            if (go)
            {
                if (!std::get<1>(*i) ->IsDone())
                {
                    buf << L" - Fails : \n" << std::get<1>(*i)->GetReport();
                    OutputDebugStringW(buf.str().c_str());
                    ++failed;
                }
                else
                {
                    buf << L" - OK\n";
                    OutputDebugStringW(buf.str().c_str());
                    ++passed;
                }    
            }
        }
        OutputDebugStringW(L"-----------------------------------------------------------------------------\n");
        std::wstringstream buf;
        buf << L"All tests finished : passed = " << passed << L" failed = " << failed << std::endl;
        OutputDebugStringW(buf.str().c_str());
        OutputDebugStringW(L"=============================================================================\n");
    }

private:
    std::vector<std::tuple<std::wstring, std::shared_ptr<Test> > > tests;
};

}

main.cpp:

#include "TestEngine\TestExecuter.h"

class MyTest1 : public testengine::Test
{
public:
    virtual void Run()
    {
        CHECK(1 == 0);
    }
};

class MyTest2 : public testengine::Test
{
public:
    virtual void Run()
    {
        CHECK(1 == 1);
    }
};

class MyTest3 : public testengine::Test
{
public:
    virtual void Run()
    {
        CHECK_EQUALS(1, 2);
    }
};

class MyTest4 : public testengine::Test
{
public:
    virtual void TearDown()
    {
        throw 1;
    }

    virtual void Run()
    {
        CHECK_EQUALS(3, 4);
    }
};


class MyTest5 : public testengine::Test
{
public:

    virtual void Setup()
    {
        throw 1;
    }


    virtual void TearDown()
    {
        throw 1;
    }

    virtual void Run()
    {
        CHECK_EQUALS(3, 4);
    }
};


class MyTest6 : public testengine::Test
{
public:

    virtual void TearDown()
    {
        throw 1;
    }

    virtual void Run()
    {
        throw 1;
        CHECK_EQUALS(3, 4);
    }
};

TEST(MyTest7)
{
    CHECK_NOT_EQUALS(4, 4);
}

int main(int argc, char* argv[])
{
    testengine::TestExecuter testExec;

    testExec.AddTest<MyTest1>(L"MyTest1");
    testExec.AddTest<MyTest2>(L"MyTest2");
    testExec.AddTest<MyTest3>(L"MyTest3");
    testExec.AddTest<MyTest4>(L"MyTest4");
    testExec.AddTest<MyTest5>(L"MyTest5");
    testExec.AddTest<MyTest6>(L"MyTest6");
    testExec.AddTest(MyTest7, L"MyTest7");

    testExec.RunTests();
    
    return 0;
}