[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] [RFC] pygame.event.wait_get()



I noticed another pattern I seem to consistently apply to all event
code I write.
Namely that I want to process all events during one iteration of the
main loop, but wait .
Up until recently I had used pygame.event.get() without noticing that
that essentially is a busy wait and hence migrated to the less nicely
looking

while running:
  for ev in [pygame.event.wait(), *pygame.event.get()]:
    if ev.type == ...

The patch is attached from my local git(-hub) clone and would allow to
rephrase the above to the now equivalent

while running:
  for ev in pygame.event.wait_get():
    if ev.type == ...

cheers!
mar77i
From ec5173d91442ddf00518b2b4b8685452ae6518d2 Mon Sep 17 00:00:00 2001
From: mar77i <mar77i@xxxxxxxxx>
Date: Wed, 17 Aug 2016 12:39:25 +0200
Subject: [PATCH] add pygame.{fast,}event.wait_get() -> Eventlist combines
 pygame.wait() with pygame.get() as a pre-3.5 shortcut for
 [pygame.event.wait(), *pygame.event.get()] as basis for limiting one
 iteration over the main loop per frame and one frame per iteration over the
 main loop.

---
 docs/reST/ref/event.rst | 12 ++++++++++++
 src/doc/event_doc.h     |  6 ++++++
 src/event.c             | 23 +++++++++++++++++++++++
 src/fastevent.c         | 29 +++++++++++++++++++++++++++++
 4 files changed, 70 insertions(+)

diff --git a/docs/reST/ref/event.rst b/docs/reST/ref/event.rst
index 2633ec9..a5f7c61 100644
--- a/docs/reST/ref/event.rst
+++ b/docs/reST/ref/event.rst
@@ -151,6 +151,18 @@ type and have identical attribute values. Inequality checks also work.
 
    .. ## pygame.event.wait ##
 
+.. function:: wait_get
+
+   | :sl:`wait for at least one event and get events from the queue`
+   | :sg:`wait_get() -> Eventlist`
+
+   This will get all the messages and remove them from the queue. If the queue
+   is empty this function will wait until one is created. While the program is
+   waiting it will sleep in an idle state. This is important for programs that
+   want to share the system with other applications.
+
+   .. ## pygame.event.wait_get ##
+
 .. function:: peek
 
    | :sl:`test if event types are waiting on the queue`
diff --git a/src/doc/event_doc.h b/src/doc/event_doc.h
index c936f49..705dca1 100644
--- a/src/doc/event_doc.h
+++ b/src/doc/event_doc.h
@@ -9,6 +9,8 @@
 
 #define DOC_PYGAMEEVENTWAIT "wait() -> EventType instance\nwait for a single event from the queue"
 
+#define DOC_PYGAMEEVENTWAITGET "wait_get() -> Eventlist\nwait for at least one event and get all events from the queue"
+
 #define DOC_PYGAMEEVENTPEEK "peek(type) -> bool\npeek(typelist) -> bool\ntest if event types are waiting on the queue"
 
 #define DOC_PYGAMEEVENTCLEAR "clear() -> None\nclear(type) -> None\nclear(typelist) -> None\nremove all events from the queue"
@@ -62,6 +64,10 @@ pygame.event.wait
  wait() -> EventType instance
 wait for a single event from the queue
 
+pygame.event.wait_get
+ wait_get() -> Eventlist
+wait for at least one event and get all events from the queue
+
 pygame.event.peek
  peek(type) -> bool
  peek(typelist) -> bool
diff --git a/src/event.c b/src/event.c
index 74dd7ab..eb3d8e7 100644
--- a/src/event.c
+++ b/src/event.c
@@ -683,6 +683,23 @@ pygame_wait (PyObject* self, PyObject* args)
 }
 
 static PyObject*
+pygame_wait_get (PyObject* self, PyObject* args)
+{
+    int status;
+
+    VIDEO_INIT_CHECK ();
+
+    Py_BEGIN_ALLOW_THREADS;
+    status = SDL_WaitEvent (NULL);
+    Py_END_ALLOW_THREADS;
+
+    if (!status)
+        return RAISE (PyExc_SDLError, SDL_GetError ());
+
+    return event_get (self, args);
+}
+
+static PyObject*
 pygame_poll (PyObject* self, PyObject* args)
 {
     SDL_Event event;
@@ -1014,6 +1031,12 @@ static PyMethodDef _event_methods[] =
 
     { "pump", (PyCFunction) pygame_pump, METH_NOARGS, DOC_PYGAMEEVENTPUMP },
     { "wait", (PyCFunction) pygame_wait, METH_NOARGS, DOC_PYGAMEEVENTWAIT },
+    {
+        "wait_get",
+        (PyCFunction) pygame_wait_get,
+        METH_NOARGS,
+        DOC_PYGAMEEVENTWAITGET
+	},
     { "poll", (PyCFunction) pygame_poll, METH_NOARGS, DOC_PYGAMEEVENTPOLL },
     { "clear", event_clear, METH_VARARGS, DOC_PYGAMEEVENTCLEAR },
     { "get", event_get, METH_VARARGS, DOC_PYGAMEEVENTGET },
diff --git a/src/fastevent.c b/src/fastevent.c
index e54393a..9db4198 100644
--- a/src/fastevent.c
+++ b/src/fastevent.c
@@ -130,6 +130,34 @@ fastevent_wait (PyObject * self)
     return PyEvent_New (&event);
 }
 
+/* DOC */ static char doc_wait_get[] =
+/* DOC */ "pygame.fastevent.wait_get() -> list of Events\n"
+/* DOC */ "wait for at least one event and get all events from the queue\n"
+/* DOC */ "\n"
+/* DOC */ "Returns all events from the queue. If there are no messages\n"
+/* DOC */ "waiting on the queue, this will not return until at least one is\n"
+/* DOC */ "available. Sometimes it is important to use this wait to get\n"
+/* DOC */ "events from the queue, it will allow your application to idle\n"
+/* DOC */ "when the user isn't doing anything with it.\n"
+/* DOC */ ;
+static PyObject *
+fastevent_wait_get (PyObject * self)
+{
+    int       status;
+
+    FE_INIT_CHECK ();
+
+    Py_BEGIN_ALLOW_THREADS;
+    status = FE_WaitEvent (NULL);
+    Py_END_ALLOW_THREADS;
+
+    /* FE_WaitEvent will block forever on error */
+    if (!status)
+        return RAISE (PyExc_SDLError, "unexpected error in FE_WaitEvent!");
+
+    return fastevent_get (self);
+}
+
 /* DOC */ static char doc_poll[] =
 /* DOC */ "pygame.fastevent.poll() -> Event\n"
 /* DOC */ "get an available event\n"
@@ -244,6 +272,7 @@ static PyMethodDef _fastevent_methods[] =
     {"get", (PyCFunction) fastevent_get, METH_NOARGS, doc_get},
     {"pump", (PyCFunction) fastevent_pump, METH_NOARGS, doc_pump},
     {"wait", (PyCFunction) fastevent_wait, METH_NOARGS, doc_wait},
+    {"wait_get", (PyCFunction) fastevent_wait_get, METH_NOARGS, doc_wait_get},
     {"poll", (PyCFunction) fastevent_poll, METH_NOARGS, doc_poll},
     {"post", fastevent_post, METH_O, doc_post},
 
-- 
2.9.3