什么是_GLIBCXX_USE_NANOSLEEP?

46

有一个名为_GLIBCXX_USE_NANOSLEEP的预处理宏出现在两个标准头文件中:

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

在默认情况下构建的GCC 4.7.1(Linux,64位)中,c++config.h仅包含此注释:

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

thread中,std::this_thread::sleep_for()std::this_thread::sleep_until()的定义取决于宏的定义。如果没有定义,尽管C++标准需要这两个函数,但两个函数都不会被定义。

在我的系统(glibc 2.15)中,该宏未定义,尽管nanosleep()函数(在ctime中声明)存在并可操作。

我想知道这是什么意思以及如何处理它。具体而言:

  • 是否有配置选项应该在构建GCC时使用,以默认激活此宏,如此帖子所建议的?(我在构建过程的在线文档中找不到任何内容。)
  • nanosleep()函数和该宏是否真的有关?ctime/time.h中的nanosleep()声明似乎不依赖于或定义该宏。
  • 在我的头文件或命令行上作为-D选项定义该宏时,是否存在特定风险(如此相关问题中建议的)?如果我在没有nanosleep()可用的系统上这样做,会发生什么情况,我如何找出?

更新从GCC 4.8开始,支持std::this_thread::sleep_for()等函数已自动包含在libstdc++中。不再需要配置标志。从GCC 4.8更改日志中:

this_thread::sleep_for()、this_thread::sleep_until()和this_thread::yield()定义无需使用--enable-libstdcxx-time配置选项;

但请注意,对于GCC 4.8和4.9,在Jonathan的回答中给出了进一步的细节。


1
在任何时候,configure 是否检查 nanosleep?它有什么提示? - nneonneo
@nneonneo 很好的观点。我再次运行了配置(现在使用新的4.7.2版本),但不幸的是,在配置脚本的输出中没有提到nanosleep(或与“sleep”或“time”相关的任何其他内容)。 - jogojapan
3
请尝试执行 configure --enable-libstdccxx-time,如 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52680 所示。这通常是由库维护者完成的,但这不是一个文档化的标志。 - nneonneo
有趣的是,运行命令 grep nanosleep config.log 没有任何输出? - nneonneo
@JonathanWakely 你说得对,我用了错误的拼写。不过为了nneonneo辩护,我应该说,在nneonneo链接的错误报告中,这个单词被拼错了几次。我想我实际上是从那里复制了错误的拼写。我现在正在使用正确拼写的选项重新构建 - 在libstdcxx中双“c”没有意义,我真的应该自己想出来。 - jogojapan
显示剩余8条评论
1个回答

77

当构建libstdc++时,它的configure脚本会测试您的系统以查看支持哪些功能,并根据结果在c++config.h中定义(或未定义)各种宏。

在您的情况下,configure确定POSIX nanosleep()函数不可用,并且未定义该宏。但是,正如您所说,nanosleep()在您的系统上可用。造成这种情况的原因是,除非使用--enable-libstdcxx-time选项(记录在libstdc++手册的Configuration章节, 而不是GCC configure文档),否则不会运行对其的检查。

  • 在构建GCC时是否有配置选项可以默认激活此宏,如本帖所示?(我无法在构建过程的在线文档中找到任何信息)

是的,--enable-libstdcxx-time

  • nanosleep()函数和宏之间是否真的有关系?ctime/time.h中nanosleep()的声明似乎并不依赖于该宏。

glibc函数的声明不依赖于libstdc++的宏。但是该宏告诉libstdc++是否使用该函数。

  • 在我的头文件或命令行上定义该宏是否存在特定风险(如相关问题中所建议的)?如果我在一个没有nanosleep()的系统上这样做会怎样,我该如何找出来?

这是不好的,不受支持,但会起作用。该宏是内部实现细节,应由configure设置而不是用户设置,并更改实现的内部宏的定义可能会破坏某些内容。但在这种情况下,它不会,因为唯一依赖于它的代码位于标头中,libstdc++.so中没有受到影响的库代码。

不过最好的方法是重新安装GCC并使用--enable-libstdcxx-time选项,或者如果不可能,则编辑您的c++config.h将宏定义为true。

如果您在另一个没有可用nanosleep()的系统上定义它,则在您#include <thread>时会出现编译错误。

我有一些想法来改善该配置,因此默认情况下将检查nanosleep()sched_yield(),但我还没有时间去实现它们。

更新:我已经提交了一些更改,以便在没有使用--enable-libstdcxx-time的情况下构建GCC 4.8仍将定义std::this_thread::yield()(作为无操作),并且将实现std::this_thread::sleep_for()std::this_thread::sleep_until()使用较低分辨率的::sleep()::usleep()函数而不是::nanosleep()。尽管如此,最好还是定义--enable-libstdcxx-time

另一个更新: GCC 4.9.0已发布,现在默认情况下会自动启用已知支持它们的平台上的nanosleepsched_yield。不再需要使用--enable-libstdcxx-time


5
这是一个很棒的答案,值得得到许多赞。我正在使用正确拼写的选项重新构建,一旦完成,我会汇报,但无论如何,这解释了我感兴趣的背景。 - jogojapan
只是确认一下:更正选项的拼写后,它可以工作了。再次感谢。 - jogojapan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接