Skip to content

Commit

Permalink
- Fixed read_event to correctly update the event queue tail pointer when
Browse files Browse the repository at this point in the history
  necessary. Failure to do so was leading to lost appends by enqueue_event.
- Fixed an infinite loop in spnav_remove_event, by deferring reinsertion of
  events after we finished processing the whole list.


git-svn-id: svn+ssh://svn.code.sf.net/p/spacenav/code/libspnav@15 ef983eb1-d774-4af8-acfd-baaf7b16a646
  • Loading branch information
jtsiomb committed Mar 17, 2008
1 parent a100f2b commit 3426fe0
Showing 1 changed file with 49 additions and 6 deletions.
55 changes: 49 additions & 6 deletions spnav.c
Expand Up @@ -267,6 +267,10 @@ int spnav_fd(void)
return sock;
}


/* Checks both the event queue and the daemon socket for pending events.
* In either case, it returns immediately with true/false values (doesn't block).
*/
static int event_pending(int s)
{
fd_set rd_set;
Expand All @@ -288,6 +292,10 @@ static int event_pending(int s)
return 0;
}

/* If there are events waiting in the event queue, dequeue one and
* return that, otherwise read one from the daemon socket.
* This might block unless we called event_pending() first and it returned true.
*/
static int read_event(int s, spnav_event *event)
{
int i, rd;
Expand All @@ -298,6 +306,11 @@ static int read_event(int s, spnav_event *event)
struct event_node *node = ev_queue->next;
ev_queue->next = ev_queue->next->next;

/* dequeued the last event, must update tail pointer */
if(ev_queue_tail == node) {
ev_queue_tail = ev_queue;
}

memcpy(event, &node->event, sizeof *event);
free(node);
return event->type;
Expand Down Expand Up @@ -399,18 +412,26 @@ static Bool match_events(Display *dpy, XEvent *xev, char *arg)
}
#endif

static int enqueue_event(spnav_event *event)
/* Appends an event to an event list.
* Tailptr must be a pointer to the tail pointer of the list. NULL means
* append to the global event queue.
*/
static int enqueue_event(spnav_event *event, struct event_node **tailptr)
{
struct event_node *node;
if(!(node = malloc(sizeof *node))) {
return -1;
}

memcpy(&node->event, event, sizeof node->event);
node->event = *event;
node->next = 0;

if(!tailptr) {
tailptr = &ev_queue_tail;
}

ev_queue_tail->next = node;
ev_queue_tail = node;
(*tailptr)->next = node;
*tailptr = node;
return 0;
}

Expand All @@ -430,16 +451,38 @@ int spnav_remove_events(int type)
#endif

if(sock) {
struct event_node *tmplist, *tmptail;

if(!(tmplist = tmptail = malloc(sizeof *tmplist))) {
return -1;
}
tmplist->next = 0;

/* while there are events in the event queue, or the daemon socket */
while(event_pending(sock)) {
spnav_event event;

read_event(sock, &event);
read_event(sock, &event); /* remove next event */
if(event.type != type) {
enqueue_event(&event);
/* We don't want to drop this one, wrong type. Keep the event
* in the temporary list, for deferred reinsertion
*/
enqueue_event(&event, &tmptail);
} else {
rm_count++;
}
}

/* reinsert any events we removed that we didn't mean to */
while(tmplist->next) {
struct event_node *node = tmplist->next;

enqueue_event(&node->event, 0);

free(tmplist);
tmplist = node;
}

return rm_count;
}
return 0;
Expand Down

0 comments on commit 3426fe0

Please sign in to comment.