summaryrefslogtreecommitdiff
path: root/src/grail-api.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@bitmath.org>2010-07-30 15:29:38 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-08-05 22:48:38 +0200
commit342a43e7b2ceec1dd200bffa24b052fec33f5bdc (patch)
tree291938b98037efe6e0def19e7457b9a947c484f1 /src/grail-api.c
parente0eb1015bf30fd0913db571b000ba6a83ea22660 (diff)
Introduce threading
In order to enable deferred events from grail, but the event processing in a separate thread, and have the calling thread return as quickly as possible. Signed-off-by: Henrik Rydberg <rydberg@bitmath.org>
Diffstat (limited to 'src/grail-api.c')
-rw-r--r--src/grail-api.c75
1 files changed, 71 insertions, 4 deletions
diff --git a/src/grail-api.c b/src/grail-api.c
index 19b66aa..e3b8125 100644
--- a/src/grail-api.c
+++ b/src/grail-api.c
@@ -1,6 +1,8 @@
1#include "grail-inserter.h" 1#include "grail-inserter.h"
2#include "grail-recognizer.h" 2#include "grail-recognizer.h"
3#include <grail.h> 3#include <grail.h>
4#include <pthread.h>
5#include <signal.h>
4#include <string.h> 6#include <string.h>
5#include <stdio.h> 7#include <stdio.h>
6#include <unistd.h> 8#include <unistd.h>
@@ -9,12 +11,48 @@
9#include <errno.h> 11#include <errno.h>
10#include "evbuf.h" 12#include "evbuf.h"
11 13
14static const pthread_mutex_t c_mutex = PTHREAD_MUTEX_INITIALIZER;
15static const pthread_cond_t c_wait = PTHREAD_COND_INITIALIZER;
16
12struct grail_impl { 17struct grail_impl {
13 struct touch_dev dev; 18 struct touch_dev dev;
14 struct touch_engine engine; 19 struct touch_engine engine;
15 struct evbuf evbuf; 20 struct evbuf evbuf;
21 int fd;
22 int pull, finished;
23 pthread_mutex_t mutex;
24 pthread_cond_t wait;
25 pthread_t thread;
16}; 26};
17 27
28/*
29 * While not finished, lock, wait for condition, extract the running
30 * state, unlock, then process the event queue.
31 *
32 * The processing may in principle take seconds to complete without
33 * locking up the writer side.
34 */
35static void *grail_thread(void *priv)
36{
37 struct grail_impl *x = priv;
38 int pull, finished = 0;
39 sigset_t block;
40 sigemptyset(&block);
41 sigaddset(&block, SIGIO);
42 pthread_sigmask(SIG_BLOCK, &block, NULL);
43 while (!finished) {
44 pthread_mutex_lock(&x->mutex);
45 pthread_cond_wait(&x->wait, &x->mutex);
46 pull = x->pull;
47 finished = x->finished;
48 x->pull = 0;
49 pthread_mutex_unlock(&x->mutex);
50 if (!finished && pull)
51 touch_dev_process(&x->dev);
52 }
53 pthread_exit(NULL);
54}
55
18static void tp_event(struct touch_engine *engine, 56static void tp_event(struct touch_engine *engine,
19 const struct input_event *ev) 57 const struct input_event *ev)
20{ 58{
@@ -66,10 +104,18 @@ int grail_open(struct grail *ge, int fd)
66 ret = touch_dev_open(&x->dev, fd); 104 ret = touch_dev_open(&x->dev, fd);
67 if (ret) 105 if (ret)
68 goto freegru; 106 goto freegru;
107 x->fd = fd;
108 x->mutex = c_mutex;
109 x->wait = c_wait;
110 ret = pthread_create(&x->thread, NULL, grail_thread, x);
111 if (ret)
112 goto freetouch;
113 ge->impl = x;
69 touch_engine_init(&x->engine, tp_event, tp_sync, ge); 114 touch_engine_init(&x->engine, tp_event, tp_sync, ge);
70 touch_engine_attach(&x->engine, &x->dev); 115 touch_engine_attach(&x->engine, &x->dev);
71 ge->impl = x;
72 return 0; 116 return 0;
117 freetouch:
118 touch_dev_close(&x->dev, fd);
73 freegru: 119 freegru:
74 gru_destroy(ge); 120 gru_destroy(ge);
75 freedev: 121 freedev:
@@ -82,6 +128,11 @@ int grail_open(struct grail *ge, int fd)
82void grail_close(struct grail *ge, int fd) 128void grail_close(struct grail *ge, int fd)
83{ 129{
84 struct grail_impl *x = ge->impl; 130 struct grail_impl *x = ge->impl;
131 void *status;
132 pthread_mutex_lock(&x->mutex);
133 x->finished = 1;
134 pthread_cond_signal (&x->wait);
135 pthread_mutex_unlock(&x->mutex);
85 touch_engine_detach(&x->engine, &x->dev); 136 touch_engine_detach(&x->engine, &x->dev);
86 touch_dev_close(&x->dev, fd); 137 touch_dev_close(&x->dev, fd);
87 gru_destroy(ge); 138 gru_destroy(ge);
@@ -93,12 +144,28 @@ void grail_close(struct grail *ge, int fd)
93int grail_idle(struct grail *ge, int fd, int ms) 144int grail_idle(struct grail *ge, int fd, int ms)
94{ 145{
95 struct grail_impl *x = ge->impl; 146 struct grail_impl *x = ge->impl;
96 return touch_dev_idle(&x->dev, fd, ms); 147 int ret;
148 pthread_mutex_lock(&x->mutex);
149 ret = touch_dev_idle(&x->dev, fd, ms);
150 pthread_mutex_unlock(&x->mutex);
151 return ret;
97} 152}
98 153
154/*
155 * First extract all input events to a lockless circular buffer, then,
156 * under lock, signal the worker thread.
157 *
158 * This function only blocks temporarily while signalling the worker
159 * thread.
160 */
99int grail_pull(struct grail *ge, int fd) 161int grail_pull(struct grail *ge, int fd)
100{ 162{
101 struct grail_impl *x = ge->impl; 163 struct grail_impl *x = ge->impl;
102 return touch_dev_pull(&x->dev, fd); 164 int finished = touch_dev_fetch(&x->dev, fd) < 0;
165 pthread_mutex_lock(&x->mutex);
166 x->pull = 1;
167 x->finished = finished;
168 pthread_cond_signal(&x->wait);
169 pthread_mutex_unlock(&x->mutex);
170 return 1;
103} 171}
104