Merged older cs.po file with newest pot file.
[gliv/czech_localization.git] / src / thread.c
blob58f37d15c6b09dff1a65a9e4e44d83107e477d5d
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /*******************
22 * Thread handling *
23 *******************/
25 #include <unistd.h> /* pipe() */
26 #include <stdio.h> /* perror() */
27 #include <fcntl.h> /* _O_BINARY for MinGW */
29 #include "gliv.h"
30 #include "thread.h"
31 #include "messages.h"
33 typedef struct {
34 GThreadFunc function;
35 gpointer argument;
36 gpointer result;
37 } running_data;
39 typedef struct {
40 GIOChannel *start_read;
41 GIOChannel *start_write;
42 GIOChannel *end_read;
43 GIOChannel *end_write;
44 volatile running_data *run;
45 } thread_data;
47 static GSList *threads_list = NULL;
48 G_LOCK_DEFINE_STATIC(threads_list);
50 /* This is executed in a separate thread. */
51 static gpointer thread_func(thread_data * data)
53 gchar buf = '\0';
55 for (;;) {
56 /* Wait start. */
57 g_io_channel_read_chars(data->start_read, &buf, 1, NULL, NULL);
59 data->run->result = data->run->function(data->run->argument);
61 /* Inform that we have finished. */
62 g_io_channel_write_chars(data->end_write, &buf, 1, NULL, NULL);
63 g_io_channel_flush(data->end_write, NULL);
66 return NULL;
69 /* Create a new thread. */
70 static thread_data *new_thread(void)
72 thread_data *thread = g_new(thread_data, 1);
73 gint start_pipe[2];
74 gint end_pipe[2];
75 GError *err = NULL;
77 if (pipe(start_pipe) < 0) {
78 perror("pipe(start_pipe)");
79 goto start_pipe_error;
82 if (pipe(end_pipe) < 0) {
83 perror("pipe(end_pipe)");
84 goto end_pipe_error;
87 thread->start_read = g_io_channel_unix_new(start_pipe[0]);
88 g_io_channel_set_encoding(thread->start_read, NULL, NULL);
90 thread->start_write = g_io_channel_unix_new(start_pipe[1]);
91 g_io_channel_set_encoding(thread->start_write, NULL, NULL);
93 thread->end_read = g_io_channel_unix_new(end_pipe[0]);
94 g_io_channel_set_encoding(thread->end_read, NULL, NULL);
96 thread->end_write = g_io_channel_unix_new(end_pipe[1]);
97 g_io_channel_set_encoding(thread->end_write, NULL, NULL);
99 g_thread_create((GThreadFunc) thread_func, thread, TRUE, &err);
100 if (err != NULL) {
101 g_printerr("%s\n", err->message);
102 g_error_free(err);
103 goto thread_error;
106 return thread;
108 thread_error:
109 g_io_channel_shutdown(thread->start_read, FALSE, NULL);
110 g_io_channel_shutdown(thread->start_write, FALSE, NULL);
111 g_io_channel_shutdown(thread->end_read, FALSE, NULL);
112 g_io_channel_shutdown(thread->end_write, FALSE, NULL);
114 end_pipe_error:
115 close(start_pipe[0]);
116 close(start_pipe[1]);
118 start_pipe_error:
119 return NULL;
122 static thread_data *find_free_thread(void)
124 GSList *node;
125 thread_data *thread = NULL;
127 for (node = threads_list; node != NULL; node = node->next) {
128 thread_data *node_thread;
130 node_thread = node->data;
131 if (node_thread->run == NULL) {
132 thread = node_thread;
133 break;
137 if (thread == NULL) {
138 thread = new_thread();
139 if (thread != NULL)
140 threads_list = g_slist_prepend(threads_list, thread);
143 return thread;
146 /* Called when a threaded job is finished. */
147 static gboolean done(GIOChannel * tmp1, GIOCondition tmp2,
148 volatile GThreadFunc * f)
150 *f = NULL;
151 return FALSE;
154 gpointer do_threaded(GThreadFunc f, gpointer arg)
156 thread_data *thread;
157 gpointer result;
158 gchar buf = '\0';
160 G_LOCK(threads_list);
161 thread = find_free_thread();
162 if (thread == NULL) {
163 G_UNLOCK(threads_list);
164 g_printerr(_("Cannot use a thread\n"));
165 return f(arg);
168 thread->run = g_new(running_data, 1);
169 thread->run->function = f;
170 thread->run->argument = arg;
172 G_UNLOCK(threads_list);
174 g_io_add_watch(thread->end_read, G_IO_IN, (GIOFunc) done,
175 (gpointer) & thread->run->function);
177 /* Start. */
178 g_io_channel_write_chars(thread->start_write, &buf, 1, NULL, NULL);
179 g_io_channel_flush(thread->start_write, NULL);
181 while (thread->run->function != NULL)
182 gtk_main_iteration();
184 g_io_channel_read_chars(thread->end_read, &buf, 1, NULL, NULL);
185 result = thread->run->result;
186 g_free((gpointer) thread->run);
187 thread->run = NULL;
189 return result;