]> git.meshlink.io Git - catta/blob - src/thread-watch.c
don't call pthread_sigmask on windows (MingW defines it as a no-op anyway)
[catta] / src / thread-watch.c
1 /***
2   This file is part of catta.
3
4   catta is free software; you can redistribute it and/or modify it
5   under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2.1 of the
7   License, or (at your option) any later version.
8
9   catta is distributed in the hope that it will be useful, but WITHOUT
10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12   Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with catta; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17   USA.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <sys/poll.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <pthread.h>
32 #include <signal.h>
33
34 #include <catta/llist.h>
35 #include <catta/malloc.h>
36 #include <catta/timeval.h>
37 #include <catta/simple-watch.h>
38 #include <catta/thread-watch.h>
39
40 struct CattaThreadedPoll {
41     CattaSimplePoll *simple_poll;
42     pthread_t thread_id;
43     pthread_mutex_t mutex;
44     int thread_running;
45     int retval;
46 };
47
48 static int poll_func(struct pollfd *ufds, unsigned int nfds, int timeout, void *userdata) {
49     pthread_mutex_t *mutex = userdata;
50     int r;
51
52     /* Before entering poll() we unlock the mutex, so that
53      * catta_simple_poll_quit() can succeed from another thread. */
54
55     pthread_mutex_unlock(mutex);
56     r = poll(ufds, nfds, timeout);
57     pthread_mutex_lock(mutex);
58
59     return r;
60 }
61
62 static void* thread(void *userdata){
63     CattaThreadedPoll *p = userdata;
64
65 #ifndef _WIN32
66     sigset_t mask;
67
68     /* Make sure that signals are delivered to the main thread */
69     sigfillset(&mask);
70     pthread_sigmask(SIG_BLOCK, &mask, NULL);
71 #endif
72
73     pthread_mutex_lock(&p->mutex);
74     p->retval = catta_simple_poll_loop(p->simple_poll);
75     pthread_mutex_unlock(&p->mutex);
76
77     return NULL;
78 }
79
80 CattaThreadedPoll *catta_threaded_poll_new(void) {
81     CattaThreadedPoll *p;
82
83     if (!(p = catta_new(CattaThreadedPoll, 1)))
84         goto fail; /* OOM */
85
86     if (!(p->simple_poll = catta_simple_poll_new()))
87         goto fail;
88
89     pthread_mutex_init(&p->mutex, NULL);
90
91     catta_simple_poll_set_func(p->simple_poll, poll_func, &p->mutex);
92
93     p->thread_running = 0;
94
95     return p;
96
97 fail:
98     if (p) {
99         if (p->simple_poll) {
100             catta_simple_poll_free(p->simple_poll);
101             pthread_mutex_destroy(&p->mutex);
102         }
103
104         catta_free(p);
105     }
106
107     return NULL;
108 }
109
110 void catta_threaded_poll_free(CattaThreadedPoll *p) {
111     assert(p);
112
113     /* Make sure that this function is not called from the helper thread */
114     assert(!p->thread_running || !pthread_equal(pthread_self(), p->thread_id));
115
116     if (p->thread_running)
117         catta_threaded_poll_stop(p);
118
119     if (p->simple_poll)
120         catta_simple_poll_free(p->simple_poll);
121
122     pthread_mutex_destroy(&p->mutex);
123     catta_free(p);
124 }
125
126 const CattaPoll* catta_threaded_poll_get(CattaThreadedPoll *p) {
127     assert(p);
128
129     return catta_simple_poll_get(p->simple_poll);
130 }
131
132 int catta_threaded_poll_start(CattaThreadedPoll *p) {
133     assert(p);
134
135     assert(!p->thread_running);
136
137     if (pthread_create(&p->thread_id, NULL, thread, p) < 0)
138         return -1;
139
140     p->thread_running = 1;
141
142     return 0;
143 }
144
145 int catta_threaded_poll_stop(CattaThreadedPoll *p) {
146     assert(p);
147
148     if (!p->thread_running)
149         return -1;
150
151     /* Make sure that this function is not called from the helper thread */
152     assert(!pthread_equal(pthread_self(), p->thread_id));
153
154     pthread_mutex_lock(&p->mutex);
155     catta_simple_poll_quit(p->simple_poll);
156     pthread_mutex_unlock(&p->mutex);
157
158     pthread_join(p->thread_id, NULL);
159     p->thread_running = 0;
160
161     return p->retval;
162 }
163
164 void catta_threaded_poll_quit(CattaThreadedPoll *p) {
165     assert(p);
166
167     /* Make sure that this function is called from the helper thread */
168     assert(pthread_equal(pthread_self(), p->thread_id));
169
170     catta_simple_poll_quit(p->simple_poll);
171 }
172
173 void catta_threaded_poll_lock(CattaThreadedPoll *p) {
174     assert(p);
175
176     /* Make sure that this function is not called from the helper thread */
177     assert(!p->thread_running || !pthread_equal(pthread_self(), p->thread_id));
178
179     pthread_mutex_lock(&p->mutex);
180 }
181
182 void catta_threaded_poll_unlock(CattaThreadedPoll *p) {
183     assert(p);
184
185     /* Make sure that this function is not called from the helper thread */
186     assert(!p->thread_running || !pthread_equal(pthread_self(), p->thread_id));
187
188     pthread_mutex_unlock(&p->mutex);
189 }