From 20db4969c59c06c4605473fc8f36ad7e5859453b Mon Sep 17 00:00:00 2001 From: binary1248 Date: Fri, 11 Jan 2013 05:34:23 +0100 Subject: [PATCH 1/2] Added setting of the timer resolution in the Win32 implementation of Sleep and rewrote the Unix Sleep implementation to use nanosleep instead of pthread_cond_timedwait to prevent spurious wakeups from causing the function to return too early. --- src/SFML/System/CMakeLists.txt | 3 +++ src/SFML/System/Unix/SleepImpl.cpp | 38 ++++++----------------------- src/SFML/System/Win32/SleepImpl.cpp | 11 +++++++++ 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/src/SFML/System/CMakeLists.txt b/src/SFML/System/CMakeLists.txt index 6efd948c..054e36c6 100644 --- a/src/SFML/System/CMakeLists.txt +++ b/src/SFML/System/CMakeLists.txt @@ -74,6 +74,9 @@ endif() if(LINUX) set(SYSTEM_EXT_LIBS ${SYSTEM_EXT_LIBS} rt) endif() +if(WINDOWS) + set(SYSTEM_EXT_LIBS ${SYSTEM_EXT_LIBS} winmm) +endif() # define the sfml-system target sfml_add_library(sfml-system diff --git a/src/SFML/System/Unix/SleepImpl.cpp b/src/SFML/System/Unix/SleepImpl.cpp index a1640435..acec6731 100644 --- a/src/SFML/System/Unix/SleepImpl.cpp +++ b/src/SFML/System/Unix/SleepImpl.cpp @@ -26,9 +26,8 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include -#include +#include +#include namespace sf @@ -38,38 +37,17 @@ namespace priv //////////////////////////////////////////////////////////// void sleepImpl(Time time) { - // usleep is not reliable enough (it might block the - // whole process instead of just the current thread) - // so we must use pthread_cond_timedwait instead - - // this implementation is inspired from Qt - Uint64 usecs = time.asMicroseconds(); - // get the current time - timeval tv; - gettimeofday(&tv, NULL); - - // construct the time limit (current time + time to wait) + // construct the time to wait timespec ti; - ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000; - ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000); - ti.tv_nsec %= 1000000000; - - // create a mutex and thread condition - pthread_mutex_t mutex; - pthread_mutex_init(&mutex, 0); - pthread_cond_t condition; - pthread_cond_init(&condition, 0); + ti.tv_nsec = (usecs % 1000000) * 1000; + ti.tv_sec = usecs / 1000000; // wait... - pthread_mutex_lock(&mutex); - pthread_cond_timedwait(&condition, &mutex, &ti); - pthread_mutex_unlock(&mutex); - - // destroy the mutex and condition - pthread_cond_destroy(&condition); - pthread_mutex_destroy(&mutex); + while ((nanosleep(&ti, &ti) == -1) && (errno == EINTR)) + { + } } } // namespace priv diff --git a/src/SFML/System/Win32/SleepImpl.cpp b/src/SFML/System/Win32/SleepImpl.cpp index 04f567c2..2a88db41 100644 --- a/src/SFML/System/Win32/SleepImpl.cpp +++ b/src/SFML/System/Win32/SleepImpl.cpp @@ -36,7 +36,18 @@ namespace priv //////////////////////////////////////////////////////////// void sleepImpl(Time time) { + // get the supported timer resolutions on this system + TIMECAPS tc; + timeGetDevCaps(&tc, sizeof(TIMECAPS)); + + // set the timer resolution to the minimum for the Sleep call + timeBeginPeriod(tc.wPeriodMin); + + // wait... ::Sleep(time.asMilliseconds()); + + // reset the timer resolution back to the system default + timeEndPeriod(tc.wPeriodMin); } } // namespace priv From 50332a8186afa6fa910d593ea97e01a8b86ba1c9 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Mon, 7 Oct 2013 08:34:23 +0200 Subject: [PATCH 2/2] Additional comments regarding sleep implementation. --- src/SFML/System/Unix/SleepImpl.cpp | 8 ++++++-- src/SFML/System/Win32/SleepImpl.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/SFML/System/Unix/SleepImpl.cpp b/src/SFML/System/Unix/SleepImpl.cpp index acec6731..9dbbde74 100644 --- a/src/SFML/System/Unix/SleepImpl.cpp +++ b/src/SFML/System/Unix/SleepImpl.cpp @@ -39,12 +39,16 @@ void sleepImpl(Time time) { Uint64 usecs = time.asMicroseconds(); - // construct the time to wait + // Construct the time to wait timespec ti; ti.tv_nsec = (usecs % 1000000) * 1000; ti.tv_sec = usecs / 1000000; - // wait... + // 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)) { } diff --git a/src/SFML/System/Win32/SleepImpl.cpp b/src/SFML/System/Win32/SleepImpl.cpp index 2a88db41..e3c88cb4 100644 --- a/src/SFML/System/Win32/SleepImpl.cpp +++ b/src/SFML/System/Win32/SleepImpl.cpp @@ -36,17 +36,17 @@ namespace priv //////////////////////////////////////////////////////////// void sleepImpl(Time time) { - // get the supported timer resolutions on this system + // Get the supported timer resolutions on this system TIMECAPS tc; timeGetDevCaps(&tc, sizeof(TIMECAPS)); - // set the timer resolution to the minimum for the Sleep call + // Set the timer resolution to the minimum for the Sleep call timeBeginPeriod(tc.wPeriodMin); - // wait... + // Wait... ::Sleep(time.asMilliseconds()); - // reset the timer resolution back to the system default + // Reset the timer resolution back to the system default timeEndPeriod(tc.wPeriodMin); }