/home/travis/build/MoarVM/MoarVM/src/io/io.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | |
3 | | /* Delegatory functions that assert we have a capable handle, then delegate |
4 | | * through the IO table to the correct operation. */ |
5 | | |
6 | 12.0k | static MVMOSHandle * verify_is_handle(MVMThreadContext *tc, MVMObject *oshandle, const char *op) { |
7 | 12.0k | if (REPR(oshandle)->ID != MVM_REPR_ID_MVMOSHandle) |
8 | 0 | MVM_exception_throw_adhoc(tc, "%s requires an object with REPR MVMOSHandle (got %s with REPR %s)", op, STABLE(oshandle)->debug_name, REPR(oshandle)->name); |
9 | 12.0k | return (MVMOSHandle *)oshandle; |
10 | 12.0k | } |
11 | | |
12 | 12.0k | static uv_mutex_t * acquire_mutex(MVMThreadContext *tc, MVMOSHandle *handle) { |
13 | 12.0k | uv_mutex_t *mutex = handle->body.mutex; |
14 | 12.0k | uv_mutex_lock(mutex); |
15 | 12.0k | MVM_tc_set_ex_release_mutex(tc, mutex); |
16 | 12.0k | return mutex; |
17 | 12.0k | } |
18 | | |
19 | 12.0k | static void release_mutex(MVMThreadContext *tc, uv_mutex_t *mutex) { |
20 | 12.0k | uv_mutex_unlock(mutex); |
21 | 12.0k | MVM_tc_clear_ex_release_mutex(tc); |
22 | 12.0k | } |
23 | | |
24 | 201 | MVMint64 MVM_io_close(MVMThreadContext *tc, MVMObject *oshandle) { |
25 | 201 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "close"); |
26 | 201 | if (handle->body.ops->closable) { |
27 | 201 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
28 | 201 | MVMint64 ret = handle->body.ops->closable->close(tc, handle); |
29 | 201 | release_mutex(tc, mutex); |
30 | 201 | return ret; |
31 | 201 | } |
32 | 201 | else |
33 | 0 | MVM_exception_throw_adhoc(tc, "Cannot close this kind of handle"); |
34 | 201 | } |
35 | | |
36 | 1 | MVMint64 MVM_io_is_tty(MVMThreadContext *tc, MVMObject *oshandle) { |
37 | 1 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "istty"); |
38 | 1 | /* We need the extra check on is_tty because it is NULL for pipes. */ |
39 | 1 | if (handle->body.ops->introspection && handle->body.ops->introspection->is_tty) { |
40 | 1 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
41 | 1 | MVMint64 ret = handle->body.ops->introspection->is_tty(tc, handle); |
42 | 1 | release_mutex(tc, mutex); |
43 | 1 | return ret; |
44 | 1 | } |
45 | 0 | else { |
46 | 0 | return 0; |
47 | 0 | } |
48 | 1 | } |
49 | | |
50 | 0 | MVMint64 MVM_io_fileno(MVMThreadContext *tc, MVMObject *oshandle) { |
51 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "get native descriptor"); |
52 | 0 | if (handle->body.ops->introspection) { |
53 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
54 | 0 | MVMint64 ret = handle->body.ops->introspection->native_descriptor(tc, handle); |
55 | 0 | release_mutex(tc, mutex); |
56 | 0 | return ret; |
57 | 0 | } |
58 | 0 | else { |
59 | 0 | return -1; |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | 163 | void MVM_io_set_encoding(MVMThreadContext *tc, MVMObject *oshandle, MVMString *encoding_name) { |
64 | 163 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "set encoding"); |
65 | 163 | MVMROOT(tc, handle, { |
66 | 163 | const MVMuint8 encoding_flag = MVM_string_find_encoding(tc, encoding_name); |
67 | 163 | if (handle->body.ops->encodable) { |
68 | 163 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
69 | 163 | handle->body.ops->encodable->set_encoding(tc, handle, encoding_flag); |
70 | 163 | release_mutex(tc, mutex); |
71 | 163 | } |
72 | 163 | else |
73 | 163 | MVM_exception_throw_adhoc(tc, "Cannot set encoding on this kind of handle"); |
74 | 163 | }); |
75 | 163 | } |
76 | | |
77 | 6 | void MVM_io_seek(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 offset, MVMint64 flag) { |
78 | 6 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "seek"); |
79 | 6 | if (handle->body.ops->seekable) { |
80 | 6 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
81 | 6 | handle->body.ops->seekable->seek(tc, handle, offset, flag); |
82 | 6 | release_mutex(tc, mutex); |
83 | 6 | } |
84 | 6 | else |
85 | 0 | MVM_exception_throw_adhoc(tc, "Cannot seek this kind of handle"); |
86 | 6 | } |
87 | | |
88 | 9 | MVMint64 MVM_io_tell(MVMThreadContext *tc, MVMObject *oshandle) { |
89 | 9 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "tell"); |
90 | 9 | if (handle->body.ops->seekable) { |
91 | 9 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
92 | 9 | MVMint64 result = handle->body.ops->seekable->tell(tc, handle); |
93 | 9 | release_mutex(tc, mutex); |
94 | 9 | return result; |
95 | 9 | } |
96 | 9 | else |
97 | 0 | MVM_exception_throw_adhoc(tc, "Cannot tell this kind of handle"); |
98 | 9 | } |
99 | | |
100 | 7 | void MVM_io_set_separator(MVMThreadContext *tc, MVMObject *oshandle, MVMString *sep) { |
101 | 7 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "set separator"); |
102 | 7 | if (handle->body.ops->sync_readable) { |
103 | 7 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
104 | 7 | handle->body.ops->sync_readable->set_separator(tc, handle, &sep, 1); |
105 | 7 | release_mutex(tc, mutex); |
106 | 7 | } |
107 | 7 | else |
108 | 0 | MVM_exception_throw_adhoc(tc, "Cannot set a separator on this kind of handle"); |
109 | 7 | } |
110 | | |
111 | 6 | void MVM_io_set_separators(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *seps) { |
112 | 6 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "set separators"); |
113 | 6 | if (handle->body.ops->sync_readable) { |
114 | 6 | MVMint32 is_str_array = REPR(seps)->pos_funcs.get_elem_storage_spec(tc, |
115 | 6 | STABLE(seps)).boxed_primitive == MVM_STORAGE_SPEC_BP_STR; |
116 | 6 | if (is_str_array) { |
117 | 6 | uv_mutex_t *mutex; |
118 | 6 | MVMString **c_seps; |
119 | 6 | MVMuint64 i; |
120 | 6 | |
121 | 6 | MVMuint64 num_seps = MVM_repr_elems(tc, seps); |
122 | 6 | if (num_seps > 0xFFFFFF) |
123 | 0 | MVM_exception_throw_adhoc(tc, "Too many line separators"); |
124 | 6 | c_seps = MVM_malloc((num_seps ? num_seps : 1) * sizeof(MVMString *)); |
125 | 18 | for (i = 0; i < num_seps; i++) |
126 | 12 | c_seps[i] = MVM_repr_at_pos_s(tc, seps, i); |
127 | 6 | |
128 | 6 | mutex = acquire_mutex(tc, handle); |
129 | 6 | handle->body.ops->sync_readable->set_separator(tc, handle, c_seps, (MVMint32)num_seps); |
130 | 6 | release_mutex(tc, mutex); |
131 | 6 | |
132 | 6 | MVM_free(c_seps); |
133 | 6 | } |
134 | 0 | else { |
135 | 0 | MVM_exception_throw_adhoc(tc, "Set separators requires a native string array"); |
136 | 0 | } |
137 | 6 | } |
138 | 0 | else { |
139 | 0 | MVM_exception_throw_adhoc(tc, "Cannot set separators on this kind of handle"); |
140 | 0 | } |
141 | 6 | } |
142 | | |
143 | 26 | MVMString * MVM_io_readline(MVMThreadContext *tc, MVMObject *oshandle, MVMint32 chomp) { |
144 | 26 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "readline"); |
145 | 26 | if (handle->body.ops->sync_readable) { |
146 | 26 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
147 | 26 | MVMString *result = handle->body.ops->sync_readable->read_line(tc, handle, chomp); |
148 | 26 | release_mutex(tc, mutex); |
149 | 26 | return result; |
150 | 26 | } |
151 | 26 | else |
152 | 0 | MVM_exception_throw_adhoc(tc, "Cannot read lines from this kind of handle"); |
153 | 26 | } |
154 | | |
155 | 4 | MVMString * MVM_io_read_string(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 chars) { |
156 | 4 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read string"); |
157 | 4 | if (handle->body.ops->sync_readable) { |
158 | 4 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
159 | 4 | MVMString *result = handle->body.ops->sync_readable->read_chars(tc, handle, chars); |
160 | 4 | release_mutex(tc, mutex); |
161 | 4 | return result; |
162 | 4 | } |
163 | 4 | else |
164 | 0 | MVM_exception_throw_adhoc(tc, "Cannot read characters from this kind of handle"); |
165 | 4 | } |
166 | | |
167 | 4 | void MVM_io_read_bytes(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *result, MVMint64 length) { |
168 | 4 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read bytes"); |
169 | 4 | MVMint64 bytes_read; |
170 | 4 | char *buf; |
171 | 4 | |
172 | 4 | /* Ensure the target is in the correct form. */ |
173 | 4 | if (!IS_CONCRETE(result) || REPR(result)->ID != MVM_REPR_ID_VMArray) |
174 | 0 | MVM_exception_throw_adhoc(tc, "read_fhb requires a native array to write to"); |
175 | 4 | if (((MVMArrayREPRData *)STABLE(result)->REPR_data)->slot_type != MVM_ARRAY_U8 |
176 | 2 | && ((MVMArrayREPRData *)STABLE(result)->REPR_data)->slot_type != MVM_ARRAY_I8) |
177 | 0 | MVM_exception_throw_adhoc(tc, "read_fhb requires a native array of uint8 or int8"); |
178 | 4 | |
179 | 4 | if (length < 1) |
180 | 0 | MVM_exception_throw_adhoc(tc, "Out of range: attempted to read %"PRId64" bytes from filehandle", length); |
181 | 4 | |
182 | 4 | if (handle->body.ops->sync_readable) { |
183 | 4 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
184 | 4 | bytes_read = handle->body.ops->sync_readable->read_bytes(tc, handle, &buf, length); |
185 | 4 | release_mutex(tc, mutex); |
186 | 4 | } |
187 | 4 | else |
188 | 0 | MVM_exception_throw_adhoc(tc, "Cannot read characters from this kind of handle"); |
189 | 4 | |
190 | 4 | /* Stash the data in the VMArray. */ |
191 | 4 | ((MVMArray *)result)->body.slots.i8 = (MVMint8 *)buf; |
192 | 4 | ((MVMArray *)result)->body.start = 0; |
193 | 4 | ((MVMArray *)result)->body.ssize = bytes_read; |
194 | 4 | ((MVMArray *)result)->body.elems = bytes_read; |
195 | 4 | } |
196 | | |
197 | 176 | MVMString * MVM_io_slurp(MVMThreadContext *tc, MVMObject *oshandle) { |
198 | 176 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "slurp"); |
199 | 176 | if (handle->body.ops->sync_readable) { |
200 | 176 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
201 | 176 | MVMString *result = handle->body.ops->sync_readable->slurp(tc, handle); |
202 | 176 | release_mutex(tc, mutex); |
203 | 176 | return result; |
204 | 176 | } |
205 | 176 | else |
206 | 0 | MVM_exception_throw_adhoc(tc, "Cannot slurp this kind of handle"); |
207 | 176 | } |
208 | | |
209 | 11.4k | MVMint64 MVM_io_write_string(MVMThreadContext *tc, MVMObject *oshandle, MVMString *str, MVMint8 addnl) { |
210 | 11.4k | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write string"); |
211 | 11.4k | if (str == NULL) |
212 | 0 | MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL string given"); |
213 | 11.4k | if (handle->body.ops->sync_writable) { |
214 | 11.4k | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
215 | 11.4k | MVMint64 result = handle->body.ops->sync_writable->write_str(tc, handle, str, addnl); |
216 | 11.4k | release_mutex(tc, mutex); |
217 | 11.4k | return result; |
218 | 11.4k | } |
219 | 11.4k | else |
220 | 0 | MVM_exception_throw_adhoc(tc, "Cannot write a string to this kind of handle"); |
221 | 11.4k | } |
222 | | |
223 | 2 | void MVM_io_write_bytes(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *buffer) { |
224 | 2 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write bytes"); |
225 | 2 | char *output; |
226 | 2 | MVMint64 output_size; |
227 | 2 | |
228 | 2 | /* Ensure the target is in the correct form. */ |
229 | 2 | if (!IS_CONCRETE(buffer) || REPR(buffer)->ID != MVM_REPR_ID_VMArray) |
230 | 0 | MVM_exception_throw_adhoc(tc, "write_fhb requires a native array to read from"); |
231 | 2 | if (((MVMArrayREPRData *)STABLE(buffer)->REPR_data)->slot_type != MVM_ARRAY_U8 |
232 | 0 | && ((MVMArrayREPRData *)STABLE(buffer)->REPR_data)->slot_type != MVM_ARRAY_I8) |
233 | 0 | MVM_exception_throw_adhoc(tc, "write_fhb requires a native array of uint8 or int8"); |
234 | 2 | |
235 | 2 | output = (char *)(((MVMArray *)buffer)->body.slots.i8 + ((MVMArray *)buffer)->body.start); |
236 | 2 | output_size = ((MVMArray *)buffer)->body.elems; |
237 | 2 | |
238 | 2 | if (handle->body.ops->sync_writable) { |
239 | 2 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
240 | 2 | handle->body.ops->sync_writable->write_bytes(tc, handle, output, output_size); |
241 | 2 | release_mutex(tc, mutex); |
242 | 2 | } |
243 | 2 | else |
244 | 0 | MVM_exception_throw_adhoc(tc, "Cannot write bytes to this kind of handle"); |
245 | 2 | } |
246 | | |
247 | | MVMObject * MVM_io_read_chars_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue, |
248 | 0 | MVMObject *schedulee, MVMObject *async_type) { |
249 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read chars asynchronously"); |
250 | 0 | if (handle->body.ops->async_readable) { |
251 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
252 | 0 | MVMObject *result = (MVMObject *)handle->body.ops->async_readable->read_chars(tc, |
253 | 0 | handle, queue, schedulee, async_type); |
254 | 0 | release_mutex(tc, mutex); |
255 | 0 | return result; |
256 | 0 | } |
257 | 0 | else |
258 | 0 | MVM_exception_throw_adhoc(tc, "Cannot read chars asynchronously from this kind of handle"); |
259 | 0 | } |
260 | | |
261 | | MVMObject * MVM_io_read_bytes_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue, |
262 | 0 | MVMObject *schedulee, MVMObject *buf_type, MVMObject *async_type) { |
263 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read bytes asynchronously"); |
264 | 0 | if (handle->body.ops->async_readable) { |
265 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
266 | 0 | MVMObject *result = (MVMObject *)handle->body.ops->async_readable->read_bytes(tc, |
267 | 0 | handle, queue, schedulee, buf_type, async_type); |
268 | 0 | release_mutex(tc, mutex); |
269 | 0 | return result; |
270 | 0 | } |
271 | 0 | else |
272 | 0 | MVM_exception_throw_adhoc(tc, "Cannot read bytes asynchronously from this kind of handle"); |
273 | 0 | } |
274 | | |
275 | | MVMObject * MVM_io_write_string_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue, |
276 | 0 | MVMObject *schedulee, MVMString *str, MVMObject *async_type) { |
277 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write string asynchronously"); |
278 | 0 | if (str == NULL) |
279 | 0 | MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL string given"); |
280 | 0 | if (handle->body.ops->async_writable) { |
281 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
282 | 0 | MVMObject *result = (MVMObject *)handle->body.ops->async_writable->write_str(tc, |
283 | 0 | handle, queue, schedulee, str, async_type); |
284 | 0 | release_mutex(tc, mutex); |
285 | 0 | return result; |
286 | 0 | } |
287 | 0 | else |
288 | 0 | MVM_exception_throw_adhoc(tc, "Cannot write a string asynchronously to this kind of handle"); |
289 | 0 | } |
290 | | |
291 | | MVMObject * MVM_io_write_bytes_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue, |
292 | 0 | MVMObject *schedulee, MVMObject *buffer, MVMObject *async_type) { |
293 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write buffer asynchronously"); |
294 | 0 | if (buffer == NULL) |
295 | 0 | MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL buffer given"); |
296 | 0 | if (handle->body.ops->async_writable) { |
297 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
298 | 0 | MVMObject *result = (MVMObject *)handle->body.ops->async_writable->write_bytes(tc, |
299 | 0 | handle, queue, schedulee, buffer, async_type); |
300 | 0 | release_mutex(tc, mutex); |
301 | 0 | return result; |
302 | 0 | } |
303 | 0 | else |
304 | 0 | MVM_exception_throw_adhoc(tc, "Cannot write bytes asynchronously to this kind of handle"); |
305 | 0 | } |
306 | | |
307 | | MVMObject * MVM_io_write_string_to_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue, |
308 | | MVMObject *schedulee, MVMString *str, MVMObject *async_type, |
309 | 0 | MVMString *host, MVMint64 port) { |
310 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write string asynchronously to destination"); |
311 | 0 | if (str == NULL) |
312 | 0 | MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL string given"); |
313 | 0 | if (handle->body.ops->async_writable_to) { |
314 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
315 | 0 | MVMObject *result = (MVMObject *)handle->body.ops->async_writable_to->write_str_to(tc, |
316 | 0 | handle, queue, schedulee, str, async_type, host, port); |
317 | 0 | release_mutex(tc, mutex); |
318 | 0 | return result; |
319 | 0 | } |
320 | 0 | else |
321 | 0 | MVM_exception_throw_adhoc(tc, "Cannot write a string to a destination asynchronously to this kind of handle"); |
322 | 0 | } |
323 | | |
324 | | MVMObject * MVM_io_write_bytes_to_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue, |
325 | | MVMObject *schedulee, MVMObject *buffer, MVMObject *async_type, |
326 | 0 | MVMString *host, MVMint64 port) { |
327 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write buffer asynchronously to destination"); |
328 | 0 | if (buffer == NULL) |
329 | 0 | MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL buffer given"); |
330 | 0 | if (handle->body.ops->async_writable_to) { |
331 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
332 | 0 | MVMObject *result = (MVMObject *)handle->body.ops->async_writable_to->write_bytes_to(tc, |
333 | 0 | handle, queue, schedulee, buffer, async_type, host, port); |
334 | 0 | release_mutex(tc, mutex); |
335 | 0 | return result; |
336 | 0 | } |
337 | 0 | else |
338 | 0 | MVM_exception_throw_adhoc(tc, "Cannot write bytes to a destination asynchronously to this kind of handle"); |
339 | 0 | } |
340 | | |
341 | 3 | MVMint64 MVM_io_eof(MVMThreadContext *tc, MVMObject *oshandle) { |
342 | 3 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "eof"); |
343 | 3 | if (handle->body.ops->sync_readable) { |
344 | 3 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
345 | 3 | MVMint64 result = handle->body.ops->sync_readable->eof(tc, handle); |
346 | 3 | release_mutex(tc, mutex); |
347 | 3 | return result; |
348 | 3 | } |
349 | 3 | else |
350 | 0 | MVM_exception_throw_adhoc(tc, "Cannot eof this kind of handle"); |
351 | 3 | } |
352 | | |
353 | 0 | MVMint64 MVM_io_lock(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 flag) { |
354 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "lock"); |
355 | 0 | if (handle->body.ops->lockable) { |
356 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
357 | 0 | MVMint64 result = handle->body.ops->lockable->lock(tc, handle, flag); |
358 | 0 | release_mutex(tc, mutex); |
359 | 0 | return result; |
360 | 0 | } |
361 | 0 | else |
362 | 0 | MVM_exception_throw_adhoc(tc, "Cannot lock this kind of handle"); |
363 | 0 | } |
364 | | |
365 | 0 | void MVM_io_unlock(MVMThreadContext *tc, MVMObject *oshandle) { |
366 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "unlock"); |
367 | 0 | if (handle->body.ops->lockable) { |
368 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
369 | 0 | handle->body.ops->lockable->unlock(tc, handle); |
370 | 0 | release_mutex(tc, mutex); |
371 | 0 | } |
372 | 0 | else |
373 | 0 | MVM_exception_throw_adhoc(tc, "Cannot unlock this kind of handle"); |
374 | 0 | } |
375 | | |
376 | 0 | void MVM_io_flush(MVMThreadContext *tc, MVMObject *oshandle) { |
377 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "flush"); |
378 | 0 | if (handle->body.ops->sync_writable) { |
379 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
380 | 0 | handle->body.ops->sync_writable->flush(tc, handle); |
381 | 0 | release_mutex(tc, mutex); |
382 | 0 | } |
383 | 0 | else |
384 | 0 | MVM_exception_throw_adhoc(tc, "Cannot flush this kind of handle"); |
385 | 0 | } |
386 | | |
387 | 0 | void MVM_io_truncate(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 offset) { |
388 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "truncate"); |
389 | 0 | if (handle->body.ops->sync_writable) { |
390 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
391 | 0 | handle->body.ops->sync_writable->truncate(tc, handle, offset); |
392 | 0 | release_mutex(tc, mutex); |
393 | 0 | } |
394 | 0 | else |
395 | 0 | MVM_exception_throw_adhoc(tc, "Cannot truncate this kind of handle"); |
396 | 0 | } |
397 | | |
398 | 0 | void MVM_io_connect(MVMThreadContext *tc, MVMObject *oshandle, MVMString *host, MVMint64 port) { |
399 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "connect"); |
400 | 0 | if (handle->body.ops->sockety) { |
401 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
402 | 0 | handle->body.ops->sockety->connect(tc, handle, host, port); |
403 | 0 | release_mutex(tc, mutex); |
404 | 0 | } |
405 | 0 | else |
406 | 0 | MVM_exception_throw_adhoc(tc, "Cannot connect this kind of handle"); |
407 | 0 | } |
408 | | |
409 | 0 | void MVM_io_bind(MVMThreadContext *tc, MVMObject *oshandle, MVMString *host, MVMint64 port, MVMint32 backlog) { |
410 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "bind"); |
411 | 0 | if (handle->body.ops->sockety) { |
412 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
413 | 0 | handle->body.ops->sockety->bind(tc, handle, host, port, backlog); |
414 | 0 | release_mutex(tc, mutex); |
415 | 0 | } |
416 | 0 | else |
417 | 0 | MVM_exception_throw_adhoc(tc, "Cannot bind this kind of handle"); |
418 | 0 | } |
419 | | |
420 | 0 | MVMObject * MVM_io_accept(MVMThreadContext *tc, MVMObject *oshandle) { |
421 | 0 | MVMOSHandle *handle = verify_is_handle(tc, oshandle, "accept"); |
422 | 0 | if (handle->body.ops->sockety) { |
423 | 0 | uv_mutex_t *mutex = acquire_mutex(tc, handle); |
424 | 0 | MVMObject *result = handle->body.ops->sockety->accept(tc, handle); |
425 | 0 | release_mutex(tc, mutex); |
426 | 0 | return result; |
427 | 0 | } |
428 | 0 | else |
429 | 0 | MVM_exception_throw_adhoc(tc, "Cannot accept this kind of handle"); |
430 | 0 | } |