dimanche 17 mai 2015

VC++ 11 - std::condition_variable_any not compatible with standard?

Recently, I ran into strange compilation issues on Microsoft Visual Studio 2012 (equipped with Visual C++ 11).

I ported large code base, developed mostly on Linux with extensive C++ 11 usage in mind. Despite few minor changes, everything was working fine. Except one thing: I got strange error about result type of std::condition_variable::wait_for. Its content is irrelevant here, because I checked this and...

Reference page (linked above) says:

template< class Lock, class Rep, class Period >
std::cv_status wait_for(Lock&, const std::chrono::duration<Rep, Period>&)

And:

template< class Lock, class Rep, class Period, class Predicate >
bool wait_for(Lock&, const std::chrono::duration<Rep, Period>&, Predicate)

I have used std::cv_status in some places, so I can say, I rely on its presence. However, on MSVC11, <conditional_variable> contains:

template<class _Lock, class _Rep, class _Period>
bool wait_for(_Lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time)

And:

template<class _Lock, class _Rep, class _Period, class _Predicate>
bool wait_for(_Lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time, _Predicate _Pred)

Note the different result type in first case. I was like:

Errr... what?

I checked this immediately back on Linux (g++ 4.8) and these two methods were indeed defined properly.

What's going on here? M$ has released implementation not compatible with standard?

Curious thing is, that I further investigated <condition_variable> and I have found this:

namespace cv_status {   // names for wait returns
    enum cv_status {
        timeout,
        no_timeout
    };
} // namespace cv_status

But it is:

  • unused
  • invalid (*)

Is this some well-known bug? Or perhaps standard allows implementations to do this?


(*) Standard defines enum class cv_status, not enum class cv_status::cv_status.


One more thing: wait_for calls internally wait_until, which looks like this:

bool _Res;
_Mtx_lock(&_Mtx);
_Xtrnl.unlock();
_Res = _Cnd_timedwaitX(&_Cnd, &_Mtx, _Abs_time) != _Thrd_timedout;
_Mtx_unlock(&_Mtx);
_Xtrnl.lock();
return (_Res);

So, interpretation of the result is:

  • true -> std::cv_status::no_timeout
  • false -> std::cv_status::timeout

If there was requirement, that no_timeout must be defined as 1 and timeout as 0 it would be fine, but I don't see anything like this. Actually, on Linux, there was:

enum class cv_status { no_timeout, timeout };

So these enumerators would be converted to bool in different way than on Windows.

Aucun commentaire:

Enregistrer un commentaire