aboutsummaryrefslogtreecommitdiffstats
path: root/src/gevent
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-08-17 00:13:47 +1000
committerinmarket <andrewh@inmarket.com.au>2014-08-17 00:13:47 +1000
commit14075df6989eed0c60f34ac3eeee37ff002b0db8 (patch)
tree50e8f525c09a6c27c3e8b5dbee9e71b15b782fc6 /src/gevent
parent362c25f9673f96ade74b9316b3db356c28e66aa6 (diff)
downloaduGFX-14075df6989eed0c60f34ac3eeee37ff002b0db8.tar.gz
uGFX-14075df6989eed0c60f34ac3eeee37ff002b0db8.tar.bz2
uGFX-14075df6989eed0c60f34ac3eeee37ff002b0db8.zip
Fix a bug that caused geventWait() to always fail if called with a timeout
Fix a bug that caused geventWait() to miss pending events,
Diffstat (limited to 'src/gevent')
-rw-r--r--src/gevent/gevent.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/gevent/gevent.c b/src/gevent/gevent.c
index f1dab064..0a6ebcc6 100644
--- a/src/gevent/gevent.c
+++ b/src/gevent/gevent.c
@@ -26,6 +26,7 @@
#define GLISTENER_EVENTBUSY 0x0001 // The event buffer is busy
#define GLISTENER_WAITING 0x0002 // The listener is waiting for a signal
#define GLISTENER_WITHSOURCE 0x0004 // The listener is being looked at by a source for a possible event
+#define GLISTENER_PENDING 0x0008 // There is an event waiting ready to go without a current listener
/* This mutex protects access to our tables */
static gfxMutex geventMutex;
@@ -131,10 +132,28 @@ GEvent *geventEventWait(GListener *pl, delaytime_t timeout) {
gfxMutexExit(&geventMutex);
return 0;
}
+
+ // Check to see if there is a pending event ready for us
+ if ((pl->flags & GLISTENER_PENDING)) {
+ pl->flags &= ~GLISTENER_PENDING; // We have now got this
+ pl->flags |= GLISTENER_EVENTBUSY; // Event buffer is definitely busy
+ gfxMutexExit(&geventMutex);
+ return &pl->event;
+ }
+
+ // No - wait for one.
pl->flags &= ~GLISTENER_EVENTBUSY; // Event buffer is definitely not busy
pl->flags |= GLISTENER_WAITING; // We will now be waiting on the thread
gfxMutexExit(&geventMutex);
- return gfxSemWait(&pl->waitqueue, timeout) ? &pl->event : 0;
+ if (gfxSemWait(&pl->waitqueue, timeout))
+ return &pl->event;
+
+ // Timeout - clear the waiting flag.
+ // We know this is safe as any other thread will still think there is someone waiting.
+ gfxMutexEnter(&geventMutex);
+ pl->flags &= ~GLISTENER_WAITING;
+ gfxMutexExit(&geventMutex);
+ return 0;
}
void geventEventComplete(GListener *pl) {
@@ -197,7 +216,7 @@ void geventSendEvent(GSourceListener *psl) {
// Mark it back as free and as sent. This is early to be marking as free but it protects
// if the callback alters the listener in any way
- psl->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY);
+ psl->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY|GLISTENER_PENDING);
gfxMutexExit(&geventMutex);
// Do the callback
@@ -205,11 +224,14 @@ void geventSendEvent(GSourceListener *psl) {
} else {
// Wake up the listener
+ psl->pListener->flags &= ~GLISTENER_WITHSOURCE;
if ((psl->pListener->flags & GLISTENER_WAITING)) {
- psl->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_WAITING);
+ psl->pListener->flags &= ~(GLISTENER_WAITING|GLISTENER_PENDING);
gfxSemSignal(&psl->pListener->waitqueue);
- // The listener thread will free the event buffer when ready
- }
+ } else
+ psl->pListener->flags |= GLISTENER_PENDING;
+
+ // The listener thread will free the event buffer when ready
gfxMutexExit(&geventMutex);
}
}