Что такое _GLIBCXX_USE_NANOSLEEP?

Макрос препроцессора с именем _GLIBCXX_USE_NANOSLEEP появляется в двух стандартных файлах заголовка:

  • С++/4.7.1/x86_64-неизвестно-Linux-гну/бит/c++ config.h
  • С++/4.7.1/поток

В сборке по умолчанию GCC 4.7.1 (Linux, 64-бит) единственное, что включает С++ config.h, это комментарий:

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

В то время как в потоке определение std::this_thread::sleep_for() и std::this_thread::sleep_until() зависит от макроса, который должен быть определен. Если он не определен, обе функции – хотя это требуется для С++ Standard – также не будут определены.

В моей системе (glibc 2.15) макрос не определен, хотя функция nanosleep() (объявленная в ctime) существует и работает.

Я хотел бы знать, что это значит и как с этим бороться. В частности:

  • Есть ли опция конфигурации, которая должна использоваться при создании GCC для активации этого макроса по умолчанию, как предложено этим сообщением? (Я не смог найти в онлайн-документацию процесса сборки.)
  • Есть ли связь между функцией nanosleep() и макросом? Объявление nanosleep() в ctime/time.h, похоже, не зависит от макроса или не определяет его.
  • Существует ли какой-либо конкретный риск для определения макроса в моих собственных файлах заголовков или как опция -D в командной строке (как предложено в этот связанный вопрос)? Что делать, если я делаю это в системе, где nanosleep() недоступен, и как я могу узнать об этом?

Обновление Начиная с GCC 4.8, поддержка std::this_thread::sleep_for() и тому подобное автоматически включается в libstdС++. Флаг конфигурации не требуется больше. Из журнал изменений GCC 4.8:

this_thread:: sleep_for(), this_thread:: sleep_until() и this_thread:: yield() определены без необходимости использования опции configure --enable-libstdcxx-time;

Обратите внимание на дальнейшие подробности этого для GCC 4.8 и 4.9, приведенные в ответе Джонатана.

Ответ 1

Когда libstdС++ построен, его configure script проверяет вашу систему, чтобы увидеть, какие функции поддерживаются, и на основе результатов он определяет (или отменяет) различные макросы в c++config.h

В вашем случае configure определено, что функция POSIX nanosleep() недоступна, и макрос не определен. Однако, как вы говорите, nanosleep() доступен в вашей системе. Причина, по которой она не включена configure, заключается в том, что проверки для нее даже не выполняются, если вы не используете параметр --enable-libstdcxx-time (задокументированный в главе в руководстве по libstdС++, а не GCC configure docs)

  • Есть ли опция конфигурации, которая должна использоваться при создании GCC для активации этого макроса по умолчанию, как это предлагается в этом сообщении? (Я не смог найти в онлайн-документации процесса сборки.)

Да, --enable-libstdcxx-time

  • Есть ли связь между функцией nanosleep() и макросом? Объявление nanosleep() в ctime/time.h, похоже, не зависит от макроса или не определяет его.

Объявление функции glibc не зависит от макроса libstdС++, no. Но макрос сообщает libstdС++, следует ли использовать функцию или нет.

  • Существует ли какой-либо конкретный риск при определении макроса в моих собственных файлах заголовков или в качестве опции -D в командной строке (как это предлагается в этом связанном вопросе)? Что делать, если я делаю это в системе, где nanosleep() недоступен, и как я могу узнать?

Это непослушный и неподдерживаемый, но будет работать. Макрос - это внутренняя деталь реализации, которая должна быть задана настройкой, а не пользователями, а изменение определения внутренних макросов реализации может нарушить ситуацию. Но в этом случае это произойдет не потому, что единственный код, который зависит от него, находится в заголовке, никакой код библиотеки в libstdc++.so не будет затронут.

Но лучше было бы переустановить GCC и использовать параметр --enable-libstdcxx-time, или если это невозможно, отредактируйте свой c++config.h, чтобы определить макрос в true.

Если вы определяете его в другой системе, где nanosleep() недоступен, вы получите ошибку компиляции, когда вы #include <thread>.

У меня есть некоторые идеи для улучшения этой конфигурации, поэтому nanosleep() и sched_yield() будут проверяться по умолчанию, но у меня не было времени на работу на них еще.

Обновление: Я внес некоторые изменения, так что построение GCC 4.8 без --enable-libstdcxx-time будет по-прежнему определять std::this_thread::yield() (как нет-op) и будет реализовывать std::this_thread::sleep_for() и std::this_thread::sleep_until() используя функции меньшего разрешения ::sleep() и ::usleep() вместо ::nanosleep(). Однако еще лучше определить --enable-libstdcxx-time.

Другое обновление: GCC 4.9.0 отсутствует и теперь по умолчанию автоматически включает nanosleep и sched_yield на платформах, которые, как известно, поддерживают их. Больше не нужно использовать --enable-libstdcxx-time.