Add glfwWaitEventsTimeout

This function will put the calling thread to sleep until an event
arrives or until the specified timeout has elapsed.
This commit is contained in:
Camilla Berglund 2016-02-02 21:11:16 +01:00
parent 337c77a39b
commit 5620895e88
11 changed files with 150 additions and 0 deletions

View File

@ -83,6 +83,7 @@ does not find Doxygen, the documentation will not be generated.
absolute and relative window size limits
- Added `glfwGetKeyName` for querying the layout-specific name of printable
keys
- Added `glfwWaitEventsTimeout` for waiting for events for a set amount of time
- Added `glfwGetTimerValue` and `glfwGetTimerFrequency` for raw timer access
- Added `GLFWuint64` for platform-independent 64-bit unsigned values
- Added `GLFW_NO_API` for creating window without contexts

View File

@ -58,6 +58,17 @@ processes all received events. This saves a great deal of CPU cycles and is
useful for, for example, editing tools. There must be at least one GLFW window
for this function to sleep.
If you want to wait for events but have UI elements that need periodic updates,
call @ref glfwWaitEventsTimeout.
@code
glfwWaitEventsTimeout(0.7);
@endcode
It puts the thread to sleep until at least one event has been received, or until
the specified number of seconds have elapsed. It then processes any received
events.
If the main thread is sleeping in @ref glfwWaitEvents, you can wake it from
another thread by posting an empty event to the event queue with @ref
glfwPostEmptyEvent.

View File

@ -43,6 +43,12 @@ GLFW now supports raw timer values with @ref glfwGetTimerValue and @ref
glfwGetTimerFrequency.
@subsection news_32_waittimeout Wait for events with timeout
GLFW now supports waiting for events for a set amount of time with @ref
glfwWaitEventsTimeout.
@section news_31 New features in 3.1
These are the release highlights. For a full list of changes see the

View File

@ -2633,6 +2633,7 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window
*
* @sa @ref events
* @sa glfwWaitEvents
* @sa glfwWaitEventsTimeout
*
* @since Added in version 1.0.
*
@ -2677,6 +2678,7 @@ GLFWAPI void glfwPollEvents(void);
*
* @sa @ref events
* @sa glfwPollEvents
* @sa glfwWaitEventsTimeout
*
* @since Added in version 2.5.
*
@ -2684,6 +2686,52 @@ GLFWAPI void glfwPollEvents(void);
*/
GLFWAPI void glfwWaitEvents(void);
/*! @brief Waits with timeout until events are queued and processes them.
*
* This function puts the calling thread to sleep until at least one event is
* available in the event queue, or until the specified timeout is reached. If
* one or more events are available, it behaves exactly like @ref
* glfwPollEvents, i.e. the events in the queue are processed and the function
* then returns immediately. Processing events will cause the window and input
* callbacks associated with those events to be called.
*
* The timeout value must be a positive finite number.
*
* Since not all events are associated with callbacks, this function may return
* without a callback having been called even if you are monitoring all
* callbacks.
*
* On some platforms, a window move, resize or menu operation will cause event
* processing to block. This is due to how event processing is designed on
* those platforms. You can use the
* [window refresh callback](@ref window_refresh) to redraw the contents of
* your window when necessary during such operations.
*
* On some platforms, certain callbacks may be called outside of a call to one
* of the event processing functions.
*
* If no windows exist, this function returns immediately. For synchronization
* of threads in applications that do not create windows, use your threading
* library of choice.
*
* Event processing is not required for joystick input to work.
*
* @param[in] timeout The maximum amount of time, in seconds, to wait.
*
* @reentrancy This function must not be called from a callback.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref events
* @sa glfwPollEvents
* @sa glfwWaitEvents
*
* @since Added in version 3.2.
*
* @ingroup window
*/
GLFWAPI void glfwWaitEventsTimeout(double timeout);
/*! @brief Posts an empty event to the event queue.
*
* This function posts an empty event from the current thread to the event

View File

@ -1214,6 +1214,19 @@ void _glfwPlatformWaitEvents(void)
_glfwPlatformPollEvents();
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:date
inMode:NSDefaultRunLoopMode
dequeue:YES];
if (event)
[NSApp sendEvent:event];
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

View File

@ -717,6 +717,11 @@ void _glfwPlatformPollEvents(void);
*/
void _glfwPlatformWaitEvents(void);
/*! @copydoc glfwWaitEventsTimeout
* @ingroup platform
*/
void _glfwPlatformWaitEventsTimeout(double timeout);
/*! @copydoc glfwPostEmptyEvent
* @ingroup platform
*/

View File

@ -550,6 +550,24 @@ void _glfwPlatformWaitEvents(void)
_glfwPlatformPollEvents();
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
pthread_mutex_lock(&_glfw.mir.event_mutex);
if (emptyEventQueue(_glfw.mir.event_queue))
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += (long) timeout;
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time);
}
pthread_mutex_unlock(&_glfw.mir.event_mutex);
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void)
{
}

View File

@ -1142,6 +1142,13 @@ void _glfwPlatformWaitEvents(void)
_glfwPlatformPollEvents();
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void)
{
_GLFWwindow* window = _glfw.windowListHead;

View File

@ -31,6 +31,7 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <float.h>
//////////////////////////////////////////////////////////////////////////
@ -807,6 +808,19 @@ GLFWAPI void glfwWaitEvents(void)
_glfwPlatformWaitEvents();
}
GLFWAPI void glfwWaitEventsTimeout(double timeout)
{
_GLFW_REQUIRE_INIT();
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time");
return;
}
_glfwPlatformWaitEventsTimeout(timeout);
}
GLFWAPI void glfwPostEmptyEvent(void)
{
_GLFW_REQUIRE_INIT();

View File

@ -516,6 +516,11 @@ void _glfwPlatformWaitEvents(void)
handleEvents(-1);
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
handleEvents((int) (timeout * 1e3));
}
void _glfwPlatformPostEmptyEvent(void)
{
wl_display_sync(_glfw.wl.display);

View File

@ -1912,6 +1912,28 @@ void _glfwPlatformWaitEvents(void)
_glfwPlatformPollEvents();
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
const double deadline = timeout + _glfwPlatformGetTimerValue() /
(double) _glfwPlatformGetTimerFrequency();
while (!XPending(_glfw.x11.display))
{
const double remaining = deadline - _glfwPlatformGetTimerValue() /
(double) _glfwPlatformGetTimerFrequency();
if (remaining <= 0.0)
return;
const long seconds = (long) remaining;
const long microseconds = (long) ((remaining - seconds) * 1e6);
struct timeval tv = { seconds, microseconds };
selectDisplayConnection(&tv);
}
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void)
{
XEvent event;