From a8801228363fd8da9509e1baf05a4b3a77e74b11 Mon Sep 17 00:00:00 2001 From: Vittorio Romeo Date: Tue, 11 Jan 2022 20:10:55 +0000 Subject: [PATCH] Reintroduce 'SleepImpl' sleep implementation --- include/SFML/System/Sleep.hpp | 5 ++- src/SFML/System/CMakeLists.txt | 32 ++++++++++++----- src/SFML/System/Sleep.cpp | 15 +++++--- src/SFML/System/Unix/SleepImpl.cpp | 55 +++++++++++++++++++++++++++++ src/SFML/System/Unix/SleepImpl.hpp | 48 +++++++++++++++++++++++++ src/SFML/System/Win32/SleepImpl.cpp | 55 +++++++++++++++++++++++++++++ src/SFML/System/Win32/SleepImpl.hpp | 48 +++++++++++++++++++++++++ 7 files changed, 244 insertions(+), 14 deletions(-) create mode 100644 src/SFML/System/Unix/SleepImpl.cpp create mode 100644 src/SFML/System/Unix/SleepImpl.hpp create mode 100644 src/SFML/System/Win32/SleepImpl.cpp create mode 100644 src/SFML/System/Win32/SleepImpl.hpp diff --git a/include/SFML/System/Sleep.hpp b/include/SFML/System/Sleep.hpp index e6b65dd8..9362e47f 100644 --- a/include/SFML/System/Sleep.hpp +++ b/include/SFML/System/Sleep.hpp @@ -39,7 +39,10 @@ namespace sf /// \brief Make the current thread sleep for a given duration /// /// sf::sleep is the best way to block a program or one of its -/// threads, as it doesn't consume any CPU power. +/// threads, as it doesn't consume any CPU power. Compared to +/// the standard std::this_thread::sleep_for function, this +/// one provides more accurate sleeping time thanks to some +/// platform-specific tweaks. /// /// \param duration Time to sleep /// diff --git a/src/SFML/System/CMakeLists.txt b/src/SFML/System/CMakeLists.txt index 7aebfa55..d19affc0 100644 --- a/src/SFML/System/CMakeLists.txt +++ b/src/SFML/System/CMakeLists.txt @@ -34,17 +34,31 @@ set(SRC source_group("" FILES ${SRC}) # add platform specific sources -if(SFML_OS_ANDROID) - set(PLATFORM_SRC ${PLATFORM_SRC} - ${SRCROOT}/Android/Activity.hpp - ${SRCROOT}/Android/Activity.cpp - ${SRCROOT}/Android/NativeActivity.cpp - ${SRCROOT}/Android/ResourceStream.cpp - ${SRCROOT}/Android/ResourceStream.cpp - ${SRCROOT}/Android/SuspendAwareClock.cpp +if(SFML_OS_WINDOWS) + set(PLATFORM_SRC + ${SRCROOT}/Win32/SleepImpl.cpp + ${SRCROOT}/Win32/SleepImpl.hpp ) + source_group("windows" FILES ${PLATFORM_SRC}) +else() + set(PLATFORM_SRC + ${SRCROOT}/Unix/SleepImpl.cpp + ${SRCROOT}/Unix/SleepImpl.hpp + ) + + if(SFML_OS_ANDROID) + set(PLATFORM_SRC ${PLATFORM_SRC} + ${SRCROOT}/Android/Activity.hpp + ${SRCROOT}/Android/Activity.cpp + ${SRCROOT}/Android/NativeActivity.cpp + ${SRCROOT}/Android/ResourceStream.cpp + ${SRCROOT}/Android/ResourceStream.cpp + ${SRCROOT}/Android/SuspendAwareClock.cpp + ) + endif() + + source_group("unix" FILES ${PLATFORM_SRC}) endif() -source_group("unix" FILES ${PLATFORM_SRC}) # define the sfml-system target sfml_add_library(System diff --git a/src/SFML/System/Sleep.cpp b/src/SFML/System/Sleep.cpp index 548e4b93..ee4c7305 100644 --- a/src/SFML/System/Sleep.cpp +++ b/src/SFML/System/Sleep.cpp @@ -26,8 +26,12 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#else + #include +#endif namespace sf @@ -35,8 +39,11 @@ namespace sf //////////////////////////////////////////////////////////// void sleep(Time duration) { - const auto time = std::chrono::duration(duration.asMicroseconds()); - std::this_thread::sleep_for(time); + // Note that 'std::this_thread::sleep_for' is intentionally not used here + // as it results in inconsistent sleeping times under MinGW-w64. + + if (duration >= Time::Zero) + priv::sleepImpl(duration); } } // namespace sf diff --git a/src/SFML/System/Unix/SleepImpl.cpp b/src/SFML/System/Unix/SleepImpl.cpp new file mode 100644 index 00000000..ef35dbde --- /dev/null +++ b/src/SFML/System/Unix/SleepImpl.cpp @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2022 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf::priv +{ +//////////////////////////////////////////////////////////// +void sleepImpl(Time time) +{ + const Int64 usecs = time.asMicroseconds(); + + // Construct the time to wait + timespec ti; + ti.tv_sec = static_cast(usecs / 1000000); + ti.tv_nsec = static_cast((usecs % 1000000) * 1000); + + // Wait... + // If nanosleep returns -1, we check errno. If it is EINTR + // nanosleep was interrupted and has set ti to the remaining + // duration. We continue sleeping until the complete duration + // has passed. We stop sleeping if it was due to an error. + while ((nanosleep(&ti, &ti) == -1) && (errno == EINTR)) + { + } +} + +} // namespace sf::priv diff --git a/src/SFML/System/Unix/SleepImpl.hpp b/src/SFML/System/Unix/SleepImpl.hpp new file mode 100644 index 00000000..5731ad37 --- /dev/null +++ b/src/SFML/System/Unix/SleepImpl.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2022 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SLEEPIMPLUNIX_HPP +#define SFML_SLEEPIMPLUNIX_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf::priv +{ +//////////////////////////////////////////////////////////// +/// \brief Unix implementation of sf::Sleep +/// +/// \param time Time to sleep +/// +//////////////////////////////////////////////////////////// +void sleepImpl(Time time); + +} // namespace sf::priv + + +#endif // SFML_SLEEPIMPLUNIX_HPP diff --git a/src/SFML/System/Win32/SleepImpl.cpp b/src/SFML/System/Win32/SleepImpl.cpp new file mode 100644 index 00000000..b4436405 --- /dev/null +++ b/src/SFML/System/Win32/SleepImpl.cpp @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2022 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + +namespace sf::priv +{ +//////////////////////////////////////////////////////////// +void sleepImpl(Time time) +{ + // Get the minimum supported timer resolution on this system + static const UINT periodMin = [] + { + TIMECAPS tc; + timeGetDevCaps(&tc, sizeof(TIMECAPS)); + return tc.wPeriodMin; + }(); + + // Set the timer resolution to the minimum for the Sleep call + timeBeginPeriod(periodMin); + + // Wait... + ::Sleep(static_cast(time.asMilliseconds())); + + // Reset the timer resolution back to the system default + timeEndPeriod(periodMin); +} + +} // namespace sf::priv diff --git a/src/SFML/System/Win32/SleepImpl.hpp b/src/SFML/System/Win32/SleepImpl.hpp new file mode 100644 index 00000000..10f37ac7 --- /dev/null +++ b/src/SFML/System/Win32/SleepImpl.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2022 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SLEEPIMPLWIN32_HPP +#define SFML_SLEEPIMPLWIN32_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf::priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of sf::Sleep +/// +/// \param time Time to sleep +/// +//////////////////////////////////////////////////////////// +void sleepImpl(Time time); + +} // namespace sf::priv + + +#endif // SFML_SLEEPIMPLWIN32_HPP