I had read way back when that there was a new standard with things added to the libraries like cross platform threads. I figured by now, I was behind the times, but I'd check it out and maybe update some of my libraries to work with the new standards way of doing things. According to the history page at The History of C++, the standard work was started in 2005 and was referred to as C++0x as it was expected to be done long before 2010. Hahaha. You can see the reference still in the command line options for GCC 4.6. But it took longer than expected, and the standard finally came out in 2011.
So now two years later, I 'm giving this stuff a test drive. Short answer? Its still sketchy.
My first test program should have been trivial, but I wanted each thread to have its own seeded random number generator. The page for rand() & rand_r() say that they're really not that good and you should use drand48, but I wasn't getting even basic cross platform support for drand48_r and somewhere the include files called it out as deprecated. Sigh.
On a wild guess, I went and took a look at the excellent documentation at cppreference, and while initially I did discover that the cpp library has a rand() function, its a mutex locked singleton. Also not what I wanted. But that at least got me to the random number generator section of the Numerics library, where with the help of some web resources, I figured out that I wanted to do:
typedef std::mt19937 rnd_type ;
std::uniform_int_distribution<rnd_type::result_type> urand(0, 400) ;
rnd_type m_rseed ;
m_rseed.seed( aseed) ;
int ival= urand( m_rseed) ;
auto rnd= std::bind(urand, m_rseed) ;
int ival= rnd() ;
std::chrono::microseconds us( 1) ;So what is missing from the pieces of this example? All the chrono stuff seemed to be there, it was the sleep_for call. On my six month old linux box, GCC 4.6 complained that "class std::thread has no member named sleep_for". Cygwin was up to GCC 4.7, and should have supported it, but the package maintainers didn't compile libstdc++ with the option --enable-libstdcxx-time, and so it was conditional'd out, and Visual Studio 2012 was not having any of it either.
m_thread->sleep_for( urand( m_rseed) * us) ;
Strangely enough, a later example with a slightly different variation:
std::this_thread::sleep_for( urand( m_rseed) * us) ;worked just fine, but I was still out on two out of three platforms. I switched back to nanosleep() on the linux platforms, but was not finding anything helpful on windows, so I finally threw in a Sleep(0) on windows. That gave me the strangest behavior ever. Unlike the *nix version where I would see a very close count of cycles between two threads which were sleeping random amounts between consuming a global counter; I was getting imbalances on Windows of 40% consistently (like 364 to 136). Turns out that Sleep(0) is nothing at all like Sleep(1) and is its own private hack. So I layered a dithering routine on top of Sleep like this:
int iadd ;and finally got reasonable results from the windows version.
iadd += urand( m_rseed) ;
if ( iadd > 1000 ) { Sleep( 1) ; iadd -= 1000 ; }
else { Sleep( 0) ; }
With great trepidation, I copied the example for conditional_variable wait_for() straight from here, and except for having to use my own platform specific sleep() routine again, it worked just fine except for one little detail in Visual Studio. The example used a macro for the atomic initializer:
std::atomic<int> i = ATOMIC_VAR_INIT(0);Visual Studio was having none of it, but changing it to simply i = 0 worked just fine.
The release notes for GCC 4.8 say they no longer require platform developers to specify the --enable-libstdcxx-time, so when that comes out in the next few months (?), we'll give it a try again. I have no idea what Visual Studio's plans are.
For now you can see my hacked up samples at github, along with other random test code.
Labels: c++, c++11, programming, threads
Feb '04
Oops I dropped by satellite.
New Jets create excitement in the air.
The audience is not listening.
Mar '04
Neat chemicals you don't want to mess with.
The Lack of Practise Effect
Apr '04
Scramjets take to the air
Doing dangerous things in the fire.
The Real Way to get a job
May '04
Checking out cool tools (with the kids)
A master geek (Ink Tank flashback)
How to play with your kids