Unfortunately, C++ constructors challenged the second one:
class SampleBuffer { public: SampleBuffer(int alen) ; SampleBuffer(char const * astring) ; protected: std::unique_ptrEither you lived with two copies of the initialization code, or you created a private init() function which you called from both constructors. Not ideal, but I never worked in a group large enough that I had to worry about someone trying to call init() other than in the constructor. Still, it could happen, and that would probably be bad.m_buffer ; int m_len ; } ; SampleBuffer::SampleBuffer(int alen) : m_len(alen) { * m_buffer = new char[alen +1] ; } SampleBuffer::SampleBuffer(char const * astring) { int tmplen= strlen( astring) ; * m_buffer = new char[tmplen +1 ]; m_len= tmplen ; strncpy( * m_buffer, astring, tmplen) ; }
In C++11 they added constructor chaining which have shown up in other languages like c sharp and java. So now the constructors can look like this:
SampleBuffer::SampleBuffer(int alen) : m_len(alen) { * m_buffer = new char[alen +1] ; } SampleBuffer::SampleBuffer(char const * astring) : DRYBuffer(strlen(astring)) { strncpy( * m_buffer, astring, m_len) ; }Already an improvement, especially if you decide to change something like having m_len represent the size of the buffer including the null terminator (heaven help you tracking down that off by one error in the original with the two separate code paths).
Obviously this is just an example (only a small step above the other trivial examples out there), but I've done the init() thing before for non-trivial cases, and this will be a handy alternative.
Of course there's the issue of where you can use this, and where you can't. It looks like g++ 4.6 does not support this, but g++ 4.7 on works fine.
Labels: c++, c++11, programming
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. Strangely enough, a later example with a slightly different variation:
m_thread->sleep_for( urand( m_rseed) * us) ;
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. 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:
iadd += urand( m_rseed) ;
if ( iadd > 1000 ) { Sleep( 1) ; iadd -= 1000 ; }
else { Sleep( 0) ; }
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