46

A preprocessor macro called _GLIBCXX_USE_NANOSLEEP appears in two standard header files:

  • c++/4.7.1/x86_64-unknown-linux-gnu/bits/c++config.h
  • c++/4.7.1/thread

In a default build of GCC 4.7.1 (Linux, 64-bit) the only thing c++config.h includes is this comment:

/* Defined if nanosleep is available. */
/* #undef _GLIBCXX_USE_NANOSLEEP */

Whereas in thread, the definition of std::this_thread::sleep_for() and std::this_thread::sleep_until() depend on the macro to be defined. If it isn't defined, both functions – although required by the C++ Standard – won't be defined either.

On my system (glibc 2.15), the macro is not defined, although the nanosleep() function (declared in ctime) exists and is operational.

I'd like to know what this is all about and how to deal with it. Specifically:

  • Is there a configuration option that should be used when building GCC to activate this macro by default, as suggested by this post? (I couldn't find any in the online documentation of the build process.)
  • Is there really a relation between the nanosleep() function and the macro? The declaration of nanosleep() in ctime/time.h does not seem to depend on, or define, the macro.
  • Is there any specific risk involved in defining the macro in my own header files, or as a -D option on the command line (as suggested in this related question)? What if I do this on a system where nanosleep() is not available, and how can I actually find out?

Update From GCC 4.8 onwards, support for std::this_thread::sleep_for() and the like is automatically included in libstdc++. No configuration flag is required any more. From the GCC 4.8 change log:

this_thread::sleep_for(), this_thread::sleep_until() and this_thread::yield() are defined without requiring the configure option --enable-libstdcxx-time;

But note the further details on this for GCC 4.8 and 4.9 given in Jonathan's answer.

Community
  • 1
  • 1
jogojapan
  • 68,383
  • 11
  • 101
  • 131
  • Did you build it yourself, or is this a maintainer-supplied C++? – nneonneo Sep 21 '12 at 02:15
  • @nneonneo I built it, following the [build descriptions](http://gcc.gnu.org/install/), using no special options except user-specific directories. – jogojapan Sep 21 '12 at 02:18
  • 1
    At any point, does `configure` check for `nanosleep`? What did it say? – nneonneo Sep 21 '12 at 02:19
  • @nneonneo Good point. I ran the configuration again (now with the new 4.7.2), but unfortunately there is no mention of nanosleep (or anything else related to 'sleep' or 'time') in the output of the configuration script. – jogojapan Sep 21 '12 at 02:28
  • 3
    Try `configure --enable-libstdccxx-time` as indicated at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52680. This would likely have been done by a library maintainer, but it's not a documented flag. – nneonneo Sep 21 '12 at 02:30
  • @nneonneo Excellent find! I will try that. – jogojapan Sep 21 '12 at 02:33
  • @nneonneo I tried configuring and building with `--enable-libstdccxx-time` as well as `--enable-libstdccxx-time=rt` (each time deleting all contents of the build directory left from previous builds), but `_GLIBCXX_USE_NANOSLEEP` and `std::this_thread::sleep_for` are still not defined by default. Quite a mystery, this. – jogojapan Sep 21 '12 at 11:32
  • It is interesting. `grep nanosleep config.log` turns up nothing? – nneonneo Sep 21 '12 at 11:52
  • @nneonneo No mention of _nano_, _sleep_, or _time_ in config.log. – jogojapan Sep 22 '12 at 05:33
  • @nneonneo, it is [documented](http://gcc.gnu.org/onlinedocs/libstdc++/manual/configure.html), and you spelled it wrong (did you read the bug report?), that's why it didn't work for the OP. It's only got one 'c' i.e. `--enable-libstdcxx-time` – Jonathan Wakely Oct 18 '12 at 18:59
  • @JonathanWakely You are right, I had used the wrong spelling. In nneonneo's defence I should say, though, that it is spelled wrongly a few times in the bug report nneonneo linked to. I think I actually copied the wrong spelling from there. I am rebuilding now with the correctly spelled option -- I really should have figured this out myself double 'c' doesn't make sense in libstdcxx! – jogojapan Oct 19 '12 at 00:46
  • It's spelled wrongly in the bug report, but I pointed out that's why it wasn't working in the report too! :) http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52680#c5 – Jonathan Wakely Oct 19 '12 at 00:52
  • @JonathanWakely Yeah... I think what happened is that when I saw the error in Comment 5, I went back to [Comment 1](http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52680#c1) and copied it from there. Unfortunately, there is a spelling error there (in the first mention of the option in that comment), too. Anyway the thing is I should have thought about what the option means and realised that 'ccxx' just doesn't make sense... silly me. – jogojapan Oct 19 '12 at 01:00

1 Answers1

76

When libstdc++ is built its configure script tests your system to see what features are supported, and based on the results it defines (or undefines) various macros in c++config.h

In your case configure determined that the POSIX nanosleep() function is not available and the macro is not defined. However, as you say, nanosleep() is available on your system. The reason it's not enabled by configure is that the checks for it don't even run unless you use the --enable-libstdcxx-time option (documented in the Configuration chapter of the libstdc++ manual, not the GCC configure docs)

  • Is there a configuration option that should be used when building GCC to activate this macro by default, as suggested by this post? (I couldn't find any in the online documentation of the build process.)

Yes, --enable-libstdcxx-time

  • Is there really a relation between the nanosleep() function and the macro? The declaration of nanosleep() in ctime/time.h does not seem to depend on, or define, the macro.

The declaration of glibc's function doesn't depend on libstdc++'s macro, no. But the macro tells libstdc++ whether to use the function or not.

  • Is there any specific risk involved in defining the macro in my own header files, or as a -D option on the command line (as suggested in this related question)? What if I do this on a system where nanosleep() is not available, and how can I actually find out?

It's naughty and is unsupported, but will work. The macro is an internal implementation detail that should be set by configure and not by users and changing the definition of the implementation's internal macros can break things. But in this case it won't because the only code that depends on it is in a header, no library code in libstdc++.so is affected.

But it would be better to reinstall GCC and use the --enable-libstdcxx-time option, or if that's not possible edit your c++config.h to define the macro to true.

If you define it on a different system where nanosleep() isn't available you'll get a compilation error when you #include <thread>.

I have some ideas for improving that configuration, so nanosleep() and sched_yield() will be checked for by default, but I haven't had time to work on them yet.

Update: I've committed some changes so that building GCC 4.8 without --enable-libstdcxx-time will still define std::this_thread::yield() (as a no-op) and will implement std::this_thread::sleep_for() and std::this_thread::sleep_until() using the lower resolution ::sleep() and ::usleep() functions instead of ::nanosleep(). It's still better to define --enable-libstdcxx-time though.

Another update: GCC 4.9.0 is out and now defaults to automatically enabling nanosleep and sched_yield on platforms that are known to support them. There is no longer any need to use --enable-libstdcxx-time.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 5
    **This is a great answer and deserves many upvotes.** (I am rebuilding now with the correctly spelled option and will report once that is finished, but in any case, this explains the background I was interested in.) – jogojapan Oct 19 '12 at 00:49
  • Just to confirm: After correcting the spelling of the option, it worked. Thanks again. – jogojapan Oct 20 '12 at 10:18