f00a2e3971e391610658a4f9bc8ec68dc9c3925d
[gnome.seed] / modules / multiprocessing / seed-multiprocessing.c
1 /* -*- mode: C; indent-tabs-mode: t; tab-width: 8; c-basic-offset: 2; -*- */
2
3 /*
4  * This file is part of Seed, the GObject Introspection<->Javascript bindings.
5  *
6  * Seed is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation, either version 3 of
9  * the License, or (at your option) any later version.
10  * Seed is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with Seed.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Copyright (C) Robert Carr 2009 <carrr@rpi.edu>
18  */
19
20 #include <seed-module.h>
21
22 #include <unistd.h>
23 #include <stdio.h>
24
25 SeedEngine *eng;
26 SeedObject namespace_ref;
27 SeedClass pipe_class;
28
29 typedef struct _pipe_priv {
30   GIOChannel *read;
31   GIOChannel *write;
32 } pipe_priv;
33
34 void pipe_finalize(SeedObject pipeobj)
35 {
36   pipe_priv *priv = seed_object_get_private(pipeobj);
37   g_io_channel_unref(priv->read);
38   g_io_channel_unref(priv->write);
39   g_free(priv);
40 }
41
42 SeedObject seed_construct_pipe(SeedContext ctx,
43                                SeedObject constructor,
44                                size_t argument_count,
45                                const SeedValue arguments[],
46                                SeedException * exception)
47 {
48   SeedObject jsone, jstwo, jsret;
49   int fd1[2], fd2[2];
50   pipe_priv *priv_one, *priv_two;
51   
52   CHECK_ARG_COUNT("multiprocessing.pipe constructor", 0);
53
54   if (pipe(fd1) < 0)
55     {
56       perror("Pipe failed. Make me a javascript exception");
57       return seed_make_null(ctx);
58     }
59   if (pipe(fd2) < 0)
60     {
61       perror("Pipe failed. Make me a javascript exception");
62       return seed_make_null(ctx);
63     }
64
65   priv_one = g_new0(pipe_priv, 1);
66   priv_two = g_new0(pipe_priv, 1);
67
68   priv_one->read = g_io_channel_unix_new(fd1[0]);
69   priv_one->write = g_io_channel_unix_new(fd2[1]);
70   priv_two->read = g_io_channel_unix_new(fd2[0]);
71   priv_two->write = g_io_channel_unix_new(fd1[1]);
72
73   g_io_channel_set_close_on_unref(priv_one->read, TRUE);
74   g_io_channel_set_close_on_unref(priv_one->write, TRUE);
75   g_io_channel_set_close_on_unref(priv_two->read, TRUE);
76   g_io_channel_set_close_on_unref(priv_two->write, TRUE);
77
78   jsret = seed_make_object(ctx, 0, 0);
79   jsone = seed_make_object(ctx, pipe_class, priv_one);
80   jstwo = seed_make_object(ctx, pipe_class, priv_two);
81
82   seed_object_set_property_at_index(ctx, jsret, 0, jsone, exception);
83   seed_object_set_property_at_index(ctx, jsret, 1, jstwo, exception);
84
85   return jsret;
86 }
87
88 #define GET_CHANNEL pipe_priv * priv =          \
89     seed_object_get_private(this_object)
90
91 SeedValue seed_pipe_read(SeedContext ctx,
92                          SeedObject function,
93                          SeedObject this_object,
94                          size_t argument_count,
95                          const SeedValue arguments[], SeedException * exception)
96 {
97   SeedValue ret;
98   gchar *read;
99   GET_CHANNEL;
100   
101   CHECK_ARG_COUNT("multiprocessing.pipe.read", 0);
102
103   g_io_channel_read_line(priv->read, &read, 0, 0, 0);
104   ret = seed_value_from_string(ctx, read, exception);
105   g_free(read);
106
107   return ret;
108 }
109
110 typedef struct _marshal_privates {
111   SeedObject function;
112   SeedObject source;
113   SeedValue user_data;
114 } marshal_privates;
115
116 static gboolean gio_marshal_func(GIOChannel * source,
117                                  GIOCondition condition, gpointer data)
118 {
119   SeedGlobalContext ctx = seed_context_create(eng->group, 0);
120   SeedValue jscondition = seed_value_from_long(ctx, (glong) condition, 0);
121   SeedValue args[3], ret;
122   marshal_privates *priv = (marshal_privates *) data;
123   gboolean bret;
124
125   args[0] = priv->source;
126   args[1] = jscondition;
127   args[2] = priv->user_data;
128
129   ret = seed_object_call(ctx, priv->function, 0, 3, args, 0);
130
131   bret = seed_value_to_boolean(ctx, ret, 0);
132   seed_context_unref(ctx);
133
134   if (!bret)
135     g_free(priv);
136
137   return bret;
138 }
139
140 SeedValue seed_pipe_write(SeedContext ctx,
141                           SeedObject function,
142                           SeedObject this_object,
143                           size_t argument_count,
144                           const SeedValue arguments[],
145                           SeedException * exception)
146 {
147   gchar *data;
148   gsize written;
149   gchar eol = '\n';
150   GET_CHANNEL;
151   
152   CHECK_ARG_COUNT("multiprocessing.pipe.write", 1);
153
154   data = seed_value_to_string(ctx, arguments[0], exception);
155   g_io_channel_write_chars(priv->write, data, -1, &written, 0);
156   g_io_channel_write_chars(priv->write, &eol, 1, 0, 0);
157   g_io_channel_flush(priv->write, 0);
158
159   return seed_value_from_int(ctx, written, exception);
160 }
161
162 SeedValue seed_pipe_add_watch(SeedContext ctx,
163                               SeedObject function,
164                               SeedObject this_object,
165                               size_t argument_count,
166                               const SeedValue arguments[],
167                               SeedException * exception)
168 {
169   GET_CHANNEL;
170   
171   marshal_privates *mpriv = g_malloc0(sizeof(marshal_privates));
172   glong condition = seed_value_to_long(ctx, arguments[0], exception);
173
174   mpriv->function = arguments[1];
175   mpriv->source = this_object;
176   mpriv->user_data = argument_count == 3 ? arguments[2] : seed_make_null(ctx);
177
178   g_io_add_watch(priv->read, condition, gio_marshal_func, mpriv);
179
180   return seed_value_from_boolean(ctx, TRUE, exception);
181 }
182
183 seed_static_function pipe_funcs[] = {
184   {"read", seed_pipe_read, 0},
185   {"write", seed_pipe_write, 0},
186   {"add_watch", seed_pipe_add_watch, 0},
187   {0, 0, 0}
188 };
189
190 SeedObject
191 seed_module_init(SeedEngine * local_eng)
192 {
193   SeedObject pipe_constructor;
194   seed_class_definition pipe_class_def = seed_empty_class;
195   eng = local_eng;
196
197   namespace_ref = seed_make_object(eng->context, 0, 0);
198
199   pipe_class_def.class_name = "Pipe";
200   pipe_class_def.static_functions = pipe_funcs;
201   pipe_class_def.finalize = pipe_finalize;
202
203   pipe_class = seed_create_class(&pipe_class_def);
204
205   pipe_constructor = seed_make_constructor(eng->context,
206                                            0, seed_construct_pipe);
207
208   seed_object_set_property(eng->context,
209                            namespace_ref, "Pipe", pipe_constructor);
210
211   return namespace_ref;
212 }