g2log now with mainstream c++11 implementation

Now the thread part (and much more) of C++11 is available for free, for the mainstream C++ developer. Visual Studio 11 (beta and free) and g++-4.7 (free) are both stable and provides a lot of C++11 features. I really recommend all c++ developers out there to upgrade their toolbox.

Of course I will do my part. I have updated the CMake configuration and I had to fix some use of std::tr1 to std::, with some include correction as well, but now g2log [code | blog | CodeProject] should work out-of-the box both for Windows and Linux developers (VS11 and g++-4.7). The dependency to just::thread is no more.

A huge debt of gratitude to Anthony Williams and his great work with just::thread. I can’t wait to see what he is going to show us next. If you are interested in concurrency and threaded software knowledge I can recommend his book C++ Concurrency in Action. It was and still is a source of inspiration for me.

At the time of this writing there is only (non-recommended) test packages for g++-4.7 on ubuntu. For the Linux developers that would like to use g++-4.7 it is much better to compile it from scratch. I have written down a simple cookbook which in large is copied from http://solarianprogrammer.com/2012/04/13/building-gcc-4-7-on-ubuntu-12-04/ but I have removed the fortran stuff and simplified it a bit.

Enjoy

—- Building gcc-4.7 on Ubuntu 12.04 [read on ] —–

Modified from http://solarianprogrammer.com/2012/04/13/building-gcc-4-7-on-ubuntu-12-04/ and hopefully made easier. You should stay away from gcc 4.7.0 and gcc 4.7.1 as they have a nasty c++ ABI bug. Instead you should go for gcc 4.7.3 (gcc-4.7-20121013.tar.bz2 ) example from this mirror http://www.netgull.com/gcc/snapshots/LATEST-4.7/ )

Get the prerequisites
sudo apt-get install libmpc-dev libgmp-dev libmpfr-dev
sudo apt-get install g++
sudo apt-get install gawk
sudo apt-get install m4
sudo apt-get install gcc-multilib g++-multilib
sudo apt-get install flex bison

Go to http://gcc.gnu.org/mirrors.html and select the last stable release or a snapshot. Please go for gcc 4.7.3 and avoid gcc 4.7.1 as the latter has a nasty C++ ABI incompatibility that might give you problems.

When configuring it below the –enable-libstdcxx-time=rt must be used or else you must compile g2log with the flag D_GLIBCXX_USE_NANOSLEEP to get things like std::this_thread::sleep_for(std::chrono::seconds(1)) to work.

Configurating g++-4.7

x64 instructions

cd /* wherever just outside the gcc-4.7.* directory*  mkdir build && cd build
  export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/
  export C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
  export CPLUS_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
 ../gcc-4.7.3/configure -build=x86_64-linux-gnu -prefix=/usr/gcc_4_7 --enable-libstdcxx-time=rt --enable-checking=release --enable-languages=c,c++ --program-suffix=-4.7

Build and install it
make

sudo ln -s /usr/lib/x86_64-linux-gnu /usr/lib64

Before doing make install
sudo ln -s /usr/lib/x86_64-linux-gnu /usr/lib64
then
sudo make install

x86 instructions

With my old dual-core x86 I ran into some problems for installing gcc 4.7. Finally I looked at both the solarianprogrammer blog comments and ask-ubuntu before I got it right. It is also important to get the machine type right.

Use ‘uname -m‘ which should output i386 or i686 which is the prefix you should use below. On my installation I used i386 so update your installation for every “i386” prefix below according to your machine type.

export LIBRARY_PATH=/usr/lib/i386-linux-gnu
export C_INCLUDE_PATH=/usr/include/i386-linux-gnu
export CPLUS_INCLUDE_PATH=/usr/include/i386-linux-gnu
export LD_LIBRARY_PATH=/usr/gcc_4_7/lib

For each gmp, mpfr and mpc cd into respective directory and do 
mkdir build  then (in order)

gmp:
cd gmp-5.0.5/build/
../configure --prefix=/usr/gcc_4_7 --build=i386-linux-gnu
make
sudo make install
mpfr: 
cd mpfr-3.1.1/build
../configure --build=i386-linux-gnu --prefix=/usr/gcc_4_7 --with-gmp=/usr/gcc_4_7
make
sudo make install
mpc: 
cd mpc-1.0/build
../configure --build=i386-linux-gnu --prefix=/usr/gcc_4_7 --with-gmp=/usr/gcc_4_7 --with-mpfr=/usr/gcc_4_7
make
sudo make install
gcc: done outside the gcc source directory
mkdir build && cd build
../gcc-4.7-20121013/configure --build=i386-linux-gnu --prefix=/usr/gcc_4_7 --enable-libstdcxx-time=rt --with-gmp=/usr/gcc_4_7 --with-mpfr=/usr/gcc_4_7 --with-mpc=/usr/gcc_4_7 --enable-checking=release --enable-languages=c,c++ --program-suffix=-4.7
make
sudo make install

x86 - Fixing symlinks (could be done by path also)
sudo ln -s /usr/include/i386-linux-gnu/gnu/stubs-32.h /usr/include/gnu
sudo ln -s /usr/gcc_4_7/lib/libmpc.so.3  /usr/lib/libmpc.so.3
sudo ln -s /usr/lib/i386-linux-gnu/crti.o /usr/lib/crti.o
sudo ln -s /usr/lib/i386-linux-gnu/crt1.o /usr/lib/crt1.o
sudo ln -s /usr/lib/i386-linux-gnu/crtn.o /usr/lib/crtn.o
 

Update the paths

export PATH=/usr/gcc_4_7/bin:$PATH
Which should preferably be in your .bashrc file

In my case the make install did not quite cut it, running ./g2log-FATAL-example gave shared library error, that it could not find GLIBCXX_3.4.17 […]
Going back to the gcc build directory I then searched for libstdc++.so.6.0.17 and ran at its location strings libstdc++.so.6.0.17 | grep GLIBC which gave
GLIBCXX_34
[…]
GLIBCXX_3.4.17 Bingo!.
[…]

And to fix it  - x64
 cd /usr/lib64
  sudo ln -s libstdc++.so.6.0.17 libstdc++.so.6


And to fix it - x86
sudo rm /usr/lib/i386-linux-gnu/libstdc++.so.6
cd ~/*whatever*/gcc-4.7.3/build_test/i386-linux-gnu/libstdc++-v3
sudo cp ./src/.libs/libstdc++.so.6.0.17  /usr/lib/i386-linux-gnu/.
sudo ln -s /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17 /usr/lib/i386-linux-gnu/libstdc++.so.6

Another “fix” you might want to consider is to change the g++, gcc, gcov links in /usr/bin to point to /usr/gcc_4_7/bin/g++-4.7 (etc for gcc and gcov). That way you do not have to specify to use the g++-4.7 compiler in the CMakeFile.txt or on cmake command line, i.e
cmake ..
instead of
cmake .. -DCMAKE_CXX_COMPILER=g++-4.7

Test your c++11 compiler and libraries with code examples
(as suggested in the article above)

Program to test the new C++11 lambda syntax

//lambda1.cpp
#include <iostream>

using namespace std;
int main()
{
cout << [](int m, int n) { return m + n;} (2,4) << endl;
return 0;
}

Compiling and running the above lambda example will return …6:
g++-4.7 -std=c++11 lambda1.cpp -o lambda1
./lambda1
6

IMPORTANT: Make sure that it also has support for threads

Be sure to verify that it works with std::threads. In my fiddling of making gcc 4.7.3 work I did see that sometimes the gcc seemed to compile and install fine but the example below only crashed.

The thread1.cpp example below would typically crash like this:

ubuntu:~/tmp$ g++-4.7 -std=c++11 thread1.cpp -o thread1
ubuntu:~/tmp$ ./thread1 
terminate called after throwing an instance of 'std::system_error'
  what():  Operation not permitted
Aborted (core dumped)

A correct build and install should enable the code below to work without a crash.


// thread1.cpp
#include <iostream>
#include <thread>

//This function will be called from a thread
void call_from_thread() {
std::cout << "Hello, World!" << std::endl;
}

int main() {
std::thread t1(call_from_thread);
t1.join();
return 0;
}

g++-4.7 -std=c++11 thread1.cpp -o thread1
./thread1
Hello, World!

Last, verify that more advanced concurrency features work
Program to test future and packaged_task

#include <iostream>
#include <future>
#include <thread>

int main()
{
std::packaged_task<std::string()> task([](){return "Hello from the past";}); // wrap the function
std::future<std::string> result = task.get_future();  // get a future
std::thread(std::move(task)).detach(); // launch on a thread
std::cout << "Waiting for past to catch up ...";
result.wait();
std::cout << "Done!\nThe message : '" << result.get() << "' \n";
}

g++ -std=c++11 future1.cpp -o future
 ./future
Waiting for past to catch up …Done!
The message is: ‘Hello from the past’

Now you are ready for g2log with C++11 thanks to g++-4.7

Advertisements

About kjellkod

Software Engineer by trade, (former?) Martial Artist and Champion by strong will and small skill... and a Swede by nationality :)
This entry was posted in C++, Software Engineering. Bookmark the permalink.

22 Responses to g2log now with mainstream c++11 implementation

  1. eihero says:

    Mr. kjellkod,
    Awesome library! Works perfectly in Win8 + VC11, thanks for your great sharing~ =)

    • kjellkod says:

      Thank you @eihero. Great to get feedback and to hear that coders are using it.

      With more windows usage maybe it is time for me to add crash–g2log-stackdump to the Windows code(stackwalker64) similar to Linux? (Unless some sharp coder out there beats me to the punch *hint*)

      • eihero says:

        Wow! That will be very cool! Can’t wait for it!
        Again thanks to your works and guidance for the reference.

  2. kikijiki says:

    Hi Kjellkod, thanks again for your very nice library.
    I have a question, how can I add support for wide strings?

  3. kjellkod says:

    @kikijiki

    Cool, thanks for sharing. I have mostly used g2log in the linux domain with English so wchar_t has not been considered so far. I am very happy to hear that you found a solution and many thanks for telling me (and other users) of your solution.

    Btw: How did the dll project turn out for you?
    – Kjell

    PS: In case it is important to change to wchar all over:
    In g2log.h there ious a simple define that is later used as the logentry input argument for the background worker. I.e. typedef const std::string& LogEntry;

    • kikijiki says:

      I wanted to try to stick to utf-8 on windows too, it’s quite messy sometimes!
      About the dll project, I had to interrupt it temporarily but I should be able to resume it soon, thanks for asking!

  4. Dmitry says:

    I tried to compile g2log on Mac OS X 10.8.3 with Clang++
    Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn)
    Target: x86_64-apple-darwin12.3.0

    Here is error:

    In file included from /Users/apple/Lib/g2log/g2log/src/g2logworker.cpp:12:
    In file included from /Users/apple/Lib/g2log/g2log/src/g2logworker.h:16:
    In file included from /usr/bin/../lib/c++/v1/future:367:
    /usr/bin/../lib/c++/v1/memory:2236:15: error: no matching constructor for initialization of
    ‘g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> >’
    __first_(_VSTD::forward(get(__first_args))…)
    ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/bin/../lib/c++/v1/memory:2414:15: note: in instantiation of function template specialization
    ‘std::__1::__libcpp_compressed_pair_imp<g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string
    ()> >, std::__1::allocator<g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> > >,
    2>::__libcpp_compressed_pair_imp<const
    g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> > &,
    std::__1::allocator<g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> > > &&, 0,
    0>’ requested here
    : base(__pc, _VSTD::move(__first_args), _VSTD::move(__second_args),
    ^
    /usr/bin/../lib/c++/v1/functional:1001:11: note: in instantiation of function template specialization
    ‘std::__1::__compressed_pair<g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> >,
    std::__1::allocator<g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> > >
    >::__compressed_pair<const g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> > &,
    std::__1::allocator<g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> > > &&>’
    requested here
    : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f),
    ^
    /usr/bin/../lib/c++/v1/functional:1027:26: note: in instantiation of member function
    ‘std::__1::__function::__func<g2::PretendToBeCopyable<std::__1::packaged_task<std::__1::basic_string ()> >,

    [… cut short … ]

  5. adrien c says:

    Hello

    I liked your approach with the g2log lib, but is there a way to log a message in a lock free manner ? the size of the message could be limited obviously, even the number of message than can be pushed in the active object before it flushes the waiting cache.

    best

    • kjellkod says:

      Sure Adrien,

      In fact the first version of the “active object” that is used as background worker used such a wait-free, lock-free circular buffer. Back then it was limited to one writer thread but it can be easily made to scale to arbitrary number of log writers. The background worker will still just be one thread.

      I have actually thought about that just recently. The wait-free (guaranteed number of steps) quality will go away but he lock-free aspect of it can be kept. There are a number of different lock-free queues out there — my personal favourite would be something similar to the “Disruptor” — but made a little simpler.

  6. mikeseven says:

    can you update your code to support clang++ 3.2+?

  7. kjellkod says:

    Hi @mikeseven. Did you see the clang workaround above?

    At the moment I am working on introducing “sinks” (log receivers: file, database, network etc) to g2log and this will be the focus for the immediate future.

    There *are* a lot of people requesting clang support. Depending on other popular requests the clang support may be pushed to a higher priority on my “to do” list but I cannot promise anything.

    If any g2log/clang user is seeing this thread:
    If you would e-mail me your g2log changes to support clang I would be more then happy to use that when/if I bring g2log to clang.

  8. Srikanth says:

    I was wondering why was boost libs not used for the required support of C++11 features including thread etc.

    • kjellkod says:

      It is supported by the language itself. I would rather use C++11 compliant compilers with the std library than bringing in a third party library like boost.

  9. ctapmex says:

    g2log compile in vs 2011, but not compile in vs 2012 (2013)

    g2logworker.cpp
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xrefwrap(175): error C2558: struct ‘g2::PretendToBeCopyable’ : no copy constructor available or copy constructor is declared ‘explicit’
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xrefwrap(173) : while compiling class template member function ‘std::_Callable_base::_Callable_base(const _Ty &)’
    with
    [
    _Ty=g2::PretendToBeCopyable
    ]
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xrefwrap(269) : see reference to function template instantiation ‘std::_Callable_base::_Callable_base(const _Ty &)’ being compiled
    with
    [
    _Ty=g2::PretendToBeCopyable
    ]
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xrefwrap(263) : see reference to class template instantiation ‘std::_Callable_base’ being compiled
    with
    [
    _Ty=g2::PretendToBeCopyable
    ]
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(189) : see reference to class template instantiation ‘std::_Callable_obj<g2::PretendToBeCopyable,false>’ being compiled
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(495) : see reference to class template instantiation ‘std::_Func_impl’ being compiled
    with
    [
    _Alloc=std::allocator<std::_Func_class>
    , _Ret=void
    ]
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional(396) : see reference to function template instantiation ‘void std::_Func_class::_Do_alloc(_Fty &&,_Alloc)’ being compiled
    […cut short …]

Leave a Reply

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

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s