Определение проблемы
Я был занят редактированием библиотеки привязок 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 менее точен (или я так прочитал).