Объяснение, почему время ожидания std :: this_thread :: sleep_for () отличается между MSVC и MinGW-GCC? - PullRequest
1 голос
/ 30 октября 2019

Определение проблемы

Я был занят редактированием библиотеки привязок lua ​​к rtmidi. Я хотел исправить совместимость MinGW-GCC и LLVM / Clang. Когда я закончил вносить изменения и компилировать привязки, я заметил странную проблему синхронизации, вызванную std::this_thread::sleep_for() по сравнению с MSVC.

Я понимаю, что между разными компиляторами должны быть некоторые различия в расписании, нов следующих примерах вы можете услышать большие проблемы с синхронизацией:

Я сузил, что это кусок кода, о котором идет речь:

lua_pushliteral(L, "sleep");
lua_pushcfunction(L, [] (lua_State *L) {
    auto s = std::chrono::duration<lua_Number>(luaL_checknumber(L, 1));
    std::this_thread::sleep_for(s);
    return 0;
});
lua_rawset(L, -3);

Очевидно, что речь идет об этих двух строках:

auto s = std::chrono::duration<lua_Number>(luaL_checknumber(L, 1));
std::this_thread::sleep_for(s);

среднее время ожидания, которое передается на sleep_for(), составляет около 0,01 с, а некоторые вызовы здесь и там находятся между 0,002 с - 0,005 с.

Устранение неполадок

Сначала я проверил, была ли проблемапредставить мою текущую версию GCC (9.2.0), используя другую версию и даже используя LLVM / Clang. И GCC 8.1.0, и LLVM / Clang 9.0.0 дают одинаковые результаты.

На данный момент я могу заключить, что со средой выполнения winpthreads происходит какое-то странное планирование, поскольку они зависят от него, а MSVC - нет. .

После этого я попытался отключить код с помощью вызова Windows Sleep(). Мне пришлось умножить на 1000, чтобы скорректировать правильное время.

Sleep(luaL_checknumber(L, 1) * 1000);

Как я и ожидал, здесь нет проблемы с синхронизацией;это говорит мне о том, что winpthreads действительно является виновником здесь.

Очевидно, я не хочу совершать звонки в Windows Sleep() и продолжать использовать sleep_for() для переносимости (как в кроссплатформенности).

Вопросы

Итак, исходя из того, что я собрал, у меня есть следующие вопросы:

  • Действительно ли winpthread является виновником? Возможно, мне не хватает некоторых определений компилятора, которые могли бы решить проблему?
  • Если winpthreads действительно является виновником, почему различия во времени так велики?
  • Если нет компилятора, определите «fix»,Что бы вы порекомендовали сделать для решения проблемы?

Чтобы частично ответить на третий вопрос (если он может прийти к нему), я подумал сделать что-то вроде:

#ifdef _WIN32 && MINGW
    #include <windows.h>
#endif

...

#ifdef _WIN32 && MINGW
    Sleep(luaL_checknumber(L, 1) * 1000);
#elif _WIN32 && MSVC
    auto s = std::chrono::duration<lua_Number>(luaL_checknumber(L, 1));
    std::this_thread::sleep_for(s);
#endif

Конечно, проблема в том, что Sleep() вызов Window менее точен (или я так прочитал).

...