OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 # distutils language = c++ | |
6 | |
7 cimport c_core | |
8 | |
9 from cpython.buffer cimport PyBUF_CONTIG | |
10 from cpython.buffer cimport PyBUF_CONTIG_RO | |
11 from cpython.buffer cimport Py_buffer | |
12 from cpython.buffer cimport PyBuffer_FillInfo | |
13 from cpython.buffer cimport PyBuffer_Release | |
14 from cpython.buffer cimport PyObject_GetBuffer | |
15 from cpython.mem cimport PyMem_Malloc, PyMem_Free | |
16 from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t | |
17 | |
18 def set_system_thunks(system_thunks_as_object): | |
19 """Bind the basic Mojo Core functions. | |
20 | |
21 This should only be used by the embedder. | |
22 """ | |
23 cdef const c_core.MojoSystemThunks* system_thunks = ( | |
24 <const c_core.MojoSystemThunks*><uintptr_t>system_thunks_as_object) | |
25 c_core.MojoSetSystemThunks(system_thunks) | |
26 | |
27 HANDLE_INVALID = c_core.MOJO_HANDLE_INVALID | |
28 RESULT_OK = c_core.MOJO_RESULT_OK | |
29 RESULT_CANCELLED = c_core.MOJO_RESULT_CANCELLED | |
30 RESULT_UNKNOWN = c_core.MOJO_RESULT_UNKNOWN | |
31 RESULT_INVALID_ARGUMENT = c_core.MOJO_RESULT_INVALID_ARGUMENT | |
32 RESULT_DEADLINE_EXCEEDED = c_core.MOJO_RESULT_DEADLINE_EXCEEDED | |
33 RESULT_NOT_FOUND = c_core.MOJO_RESULT_NOT_FOUND | |
34 RESULT_ALREADY_EXISTS = c_core.MOJO_RESULT_ALREADY_EXISTS | |
35 RESULT_PERMISSION_DENIED = c_core.MOJO_RESULT_PERMISSION_DENIED | |
36 RESULT_RESOURCE_EXHAUSTED = c_core.MOJO_RESULT_RESOURCE_EXHAUSTED | |
37 RESULT_FAILED_PRECONDITION = c_core.MOJO_RESULT_FAILED_PRECONDITION | |
38 RESULT_ABORTED = c_core.MOJO_RESULT_ABORTED | |
39 RESULT_OUT_OF_RANGE = c_core.MOJO_RESULT_OUT_OF_RANGE | |
40 RESULT_UNIMPLEMENTED = c_core.MOJO_RESULT_UNIMPLEMENTED | |
41 RESULT_INTERNAL = c_core.MOJO_RESULT_INTERNAL | |
42 RESULT_UNAVAILABLE = c_core.MOJO_RESULT_UNAVAILABLE | |
43 RESULT_DATA_LOSS = c_core.MOJO_RESULT_DATA_LOSS | |
44 RESULT_BUSY = c_core.MOJO_RESULT_BUSY | |
45 RESULT_SHOULD_WAIT = c_core.MOJO_RESULT_SHOULD_WAIT | |
46 DEADLINE_INDEFINITE = c_core.MOJO_DEADLINE_INDEFINITE | |
47 HANDLE_SIGNAL_NONE = c_core.MOJO_HANDLE_SIGNAL_NONE | |
48 HANDLE_SIGNAL_READABLE = c_core.MOJO_HANDLE_SIGNAL_READABLE | |
49 HANDLE_SIGNAL_WRITABLE = c_core.MOJO_HANDLE_SIGNAL_WRITABLE | |
50 WRITE_MESSAGE_FLAG_NONE = c_core.MOJO_WRITE_MESSAGE_FLAG_NONE | |
51 READ_MESSAGE_FLAG_NONE = c_core.MOJO_READ_MESSAGE_FLAG_NONE | |
52 READ_MESSAGE_FLAG_MAY_DISCARD = c_core.MOJO_READ_MESSAGE_FLAG_MAY_DISCARD | |
53 WRITE_DATA_FLAG_NONE = c_core.MOJO_WRITE_DATA_FLAG_NONE | |
54 WRITE_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE | |
55 READ_DATA_FLAG_NONE = c_core.MOJO_READ_DATA_FLAG_NONE | |
56 READ_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE | |
57 READ_DATA_FLAG_DISCARD = c_core.MOJO_READ_DATA_FLAG_DISCARD | |
58 READ_DATA_FLAG_QUERY = c_core.MOJO_READ_DATA_FLAG_QUERY | |
59 MAP_BUFFER_FLAG_NONE = c_core.MOJO_MAP_BUFFER_FLAG_NONE | |
60 | |
61 def get_time_ticks_now(): | |
62 """Monotonically increasing tick count representing "right now." | |
63 | |
64 See mojo/public/c/system/functions.h | |
65 """ | |
66 return c_core.MojoGetTimeTicksNow() | |
67 | |
68 cdef class _ScopedMemory: | |
69 """Allocate memory at creation, and deallocate it at destruction.""" | |
70 cdef void* memory | |
71 def __init__(self, size): | |
72 self.memory = PyMem_Malloc(size) | |
73 | |
74 def __dealloc__(self): | |
75 PyMem_Free(self.memory) | |
76 | |
77 cdef class _ScopedBuffer: | |
78 """Retrieve pointer to a buffer a creation, and release it at destruction. | |
79 """ | |
80 cdef Py_buffer _buf | |
81 cdef void* buf | |
82 cdef Py_ssize_t len | |
83 | |
84 def __init__(self, obj, flags=PyBUF_CONTIG_RO): | |
85 if obj: | |
86 if PyObject_GetBuffer(obj, &self._buf, flags) < 0: | |
87 raise TypeError("Unable to read buffer.") | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
style: Be consistent with string quotes. Stick wit
qsr
2014/08/21 12:10:05
Done.
| |
88 self.buf = self._buf.buf | |
89 self.len = self._buf.len | |
90 else: | |
91 self.buf = NULL | |
92 self.len = 0 | |
93 | |
94 def __dealloc__(self): | |
95 if self.buf: | |
96 PyBuffer_Release(&self._buf) | |
97 | |
98 def _slice_buffer(buffer, size): | |
99 """Slice the given buffer, reducing it to the given size. Return None if None | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
nit: Line break with a blank line after "...given
qsr
2014/08/21 12:10:05
Done.
| |
100 is passed in. | |
101 """ | |
102 if not buffer: | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
How about test with this?
if type(buffer) not in
qsr
2014/08/21 12:10:05
This is an internal method. Do we want to pay the
| |
103 return buffer | |
104 return buffer[:size] | |
105 | |
106 cdef class _NativeMemoryView(object): | |
107 """Create a python buffer wrapping the given memory. | |
108 | |
109 Will also retain the given handle until this object is deallocated. | |
110 """ | |
111 cdef void* _memory | |
112 cdef uint32_t _size | |
113 cdef char _read_only | |
114 cdef char _wrapped | |
115 cdef object _handle | |
116 | |
117 def __init__(self, handle): | |
118 self._handle = handle | |
119 | |
120 def __cinit__(self): | |
121 self._memory = NULL | |
122 self._size = 0 | |
123 self._read_only = True | |
124 self._wrapped = False | |
125 | |
126 cdef wrap(self, | |
127 const void* memory, | |
128 uint32_t size, | |
129 read_only=True): | |
130 """Makes this buffer wraps the given memory. | |
131 | |
132 Must be called before using this buffer, and must only be called once. | |
133 """ | |
134 assert not self._wrapped | |
135 self._wrapped = True | |
136 self._memory = <void*>memory | |
137 self._size = size | |
138 self._read_only = read_only | |
139 | |
140 # buffer interface (PEP 3118) | |
141 def __getbuffer__(self, Py_buffer *view, int flags): | |
142 assert self._wrapped | |
143 if view == NULL: | |
144 return | |
145 PyBuffer_FillInfo(view, | |
146 self, | |
147 self._memory, | |
148 self._size, | |
149 self._read_only, | |
150 flags) | |
151 | |
152 def __releasebuffer__(self, Py_buffer *view): | |
153 assert self._wrapped | |
154 pass | |
155 | |
156 # legacy buffer interface | |
157 def __getsegcount__(self, Py_ssize_t *sizes): | |
158 assert self._wrapped | |
159 if sizes != NULL: | |
160 sizes[0] = self._size | |
161 return 1 | |
162 | |
163 def __getreadbuffer__(self, Py_ssize_t index, void **data): | |
164 assert self._wrapped | |
165 if index != 0: | |
166 raise SystemError('Index out of bounds: %d' % index) | |
167 data[0] = self._memory | |
168 return self._size | |
169 | |
170 def __getwritebuffer__(self, Py_ssize_t index, void **data): | |
171 assert self._wrapped | |
172 if index != 0: | |
173 raise SystemError('Index out of bounds: %d' % index) | |
174 if self._read_only: | |
175 raise TypeError("Buffer is read-only.") | |
176 data[0] = self._memory | |
177 return self._size | |
178 | |
179 class MojoException(Exception): | |
180 """Exception wrapping a mojo result error code.""" | |
181 | |
182 def __init__(self, mojo_result): | |
183 self.mojo_result = mojo_result | |
184 | |
185 def wait_many(handles_and_signals, deadline): | |
186 """Waits on a list of handles. | |
187 | |
188 Args: | |
189 handles_and_signals: list of pairs of handle and signal. | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
nit: s/pairs/tuples/
qsr
2014/08/21 12:10:05
Done.
| |
190 | |
191 See mojo/public/c/system/functions.h | |
192 """ | |
193 cdef uint32_t length = len(handles_and_signals) | |
194 cdef _ScopedMemory handles_alloc = _ScopedMemory( | |
195 sizeof(c_core.MojoHandle) * length) | |
196 cdef _ScopedMemory signals_alloc = _ScopedMemory( | |
197 sizeof(c_core.MojoHandleSignals) * length) | |
198 cdef c_core.MojoHandle* handles = <c_core.MojoHandle*>handles_alloc.memory | |
199 cdef c_core.MojoHandleSignals* signals = ( | |
200 <c_core.MojoHandleSignals*>signals_alloc.memory) | |
201 cdef int index = 0 | |
202 for (h, s) in handles_and_signals: | |
203 handles[index] = (<Handle?>h)._mojo_handle | |
204 signals[index] = s | |
205 index += 1 | |
206 cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK | |
207 cdef c_core.MojoDeadline cdeadline = deadline | |
208 with nogil: | |
209 result = c_core.MojoWaitMany(handles, signals, length, cdeadline) | |
210 return result | |
211 | |
212 cdef class DataPipeTwoPhaseBuffer(object): | |
213 """Return value for two phases read and write. | |
214 | |
215 The buffer field contain the python buffer where data can be read or write. | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
s/contain/contains/
s/write/written/
qsr
2014/08/21 12:10:05
Done.
| |
216 When done with the buffer, the |end| method must be called with the number of | |
217 bytes read or written. | |
218 """ | |
219 | |
220 cdef object _buffer | |
221 cdef Handle _handle | |
222 cdef char _read | |
223 | |
224 def __init__(self, handle, buffer, read=True): | |
225 self._buffer = buffer | |
226 self._handle = handle | |
227 self._read = read | |
228 | |
229 def end(self, num_bytes): | |
230 self._buffer = None | |
231 cdef c_core.MojoResult result | |
232 if self._read: | |
233 result = c_core.MojoEndReadData(self._handle._mojo_handle, num_bytes) | |
234 else: | |
235 result = c_core.MojoEndWriteData(self._handle._mojo_handle, num_bytes) | |
236 self._handle = None | |
237 return result | |
238 | |
239 @property | |
240 def buffer(self): | |
241 return self._buffer | |
242 | |
243 def __dealloc__(self): | |
244 if self._buffer: | |
245 self.end(0) | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
Looks like you are doing some clean up work here b
qsr
2014/08/21 12:10:05
Hum... I was thinking about letting this pass, but
| |
246 | |
247 cdef class MappedBuffer(object): | |
248 """Return value for the |map| operation on shared buffer handles. | |
249 | |
250 The buffer field contain the python buffer where data can be read or write. | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
ditto: contains. written.
qsr
2014/08/21 12:10:05
Done.
| |
251 When done with the buffer, the |unmao| method must be called. | |
pkl (ping after 24h if needed)
2014/08/21 09:32:48
s/unmao/unmap/
qsr
2014/08/21 12:10:05
Done.
| |
252 """ | |
253 | |
254 cdef object _buffer | |
255 cdef object _handle | |
256 cdef object _cleanup | |
257 | |
258 def __init__(self, handle, buffer, cleanup): | |
259 self._buffer = buffer | |
260 self._handle = handle | |
261 self._cleanup = cleanup | |
262 | |
263 def unmap(self): | |
264 self._buffer = None | |
265 cdef c_core.MojoResult result = self._cleanup() | |
266 self._cleanup = None | |
267 self._handle = None | |
268 return result | |
269 | |
270 @property | |
271 def buffer(self): | |
272 return self._buffer | |
273 | |
274 def __dealloc__(self): | |
275 if self._buffer: | |
276 self.unmap() | |
277 | |
278 cdef class Handle(object): | |
279 """A mojo object.""" | |
280 | |
281 cdef c_core.MojoHandle _mojo_handle | |
282 | |
283 def __init__(self, mojo_handle = c_core.MOJO_HANDLE_INVALID): | |
284 self._mojo_handle = mojo_handle | |
285 | |
286 def _invalidate(self): | |
287 """Invalidate the current handle. | |
288 | |
289 The close operation is not called. It is the responsability of the caller to | |
290 ensure that the handle is not leaked. | |
291 """ | |
292 self._mojo_handle = c_core.MOJO_HANDLE_INVALID | |
293 | |
294 def is_valid(self): | |
295 """Returns whether this handle is valid.""" | |
296 return self._mojo_handle != c_core.MOJO_HANDLE_INVALID | |
297 | |
298 def close(self): | |
299 """Closes this handle. | |
300 | |
301 See mojo/public/c/system/functions.h | |
302 """ | |
303 cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK | |
304 if self.is_valid(): | |
305 result = c_core.MojoClose(self._mojo_handle) | |
306 self._invalidate() | |
307 return result | |
308 | |
309 def __dealloc__(self): | |
310 self.close() | |
311 | |
312 def wait(self, signals, deadline): | |
313 """Waits on the given handle. | |
314 | |
315 See mojo/public/c/system/functions.h | |
316 """ | |
317 cdef c_core.MojoHandle handle = self._mojo_handle | |
318 cdef c_core.MojoHandleSignals csignals = signals | |
319 cdef c_core.MojoDeadline cdeadline = deadline | |
320 cdef c_core.MojoResult result | |
321 with nogil: | |
322 result = c_core.MojoWait(handle, csignals, cdeadline) | |
323 return result | |
324 | |
325 def write_message(self, | |
326 buffer=None, | |
327 handles=None, | |
328 flags=WRITE_MESSAGE_FLAG_NONE): | |
329 """ | |
330 Writes a message to the message pipe. | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
style: move this to the line with """
qsr
2014/08/21 12:10:05
Done.
| |
331 | |
332 This method can only be used on a handle obtained from |MessagePipe()|. | |
333 | |
334 See mojo/public/c/system/message_pipe.h | |
335 """ | |
336 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) | |
337 cdef uint32_t input_buffer_length = buffer_as_buffer.len | |
338 cdef c_core.MojoHandle* input_handles = NULL | |
339 cdef uint32_t input_handles_length = 0 | |
340 cdef _ScopedMemory handles_alloc = None | |
341 if handles: | |
342 input_handles_length = len(handles) | |
343 handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) * | |
344 input_handles_length) | |
345 input_handles = <c_core.MojoHandle*>handles_alloc.memory | |
346 for i in xrange(input_handles_length): | |
347 input_handles[i] = (<Handle?>handles[i])._mojo_handle | |
348 cdef c_core.MojoResult res = c_core.MojoWriteMessage(self._mojo_handle, | |
349 buffer_as_buffer.buf, | |
350 input_buffer_length, | |
351 input_handles, | |
352 input_handles_length, | |
353 flags) | |
354 if res == c_core.MOJO_RESULT_OK and handles: | |
355 # Handles have been transferred. Let's invalidate those. | |
356 for handle in handles: | |
357 handle._invalidate() | |
358 return res | |
359 | |
360 def read_message(self, | |
361 buffer=None, | |
362 max_number_of_handles=0, | |
363 flags=READ_MESSAGE_FLAG_NONE): | |
364 """Reads a message from the message pipe. | |
365 | |
366 This method can only be used on a handle obtained from |MessagePipe()|. | |
367 | |
368 This method returns a triplet of value (code, data, sizes): | |
369 - if code is RESULT_OK, sizes will be None, and data will be a pair of | |
370 (buffer, handles) where buffer is a view of the input buffer with the read | |
371 data, and handles is a list of received handles. | |
372 - if code is RESULT_RESOURCE_EXHAUSTED, data will be None and sizes will be | |
373 a pair of (buffer_size, handles_size) where buffer_size is the size of the | |
374 next message data and handles_size is the number of handles in the next | |
375 message. | |
376 - if code is any other value, data and sizes will be None. | |
377 | |
378 See mojo/public/c/system/message_pipe.h | |
379 """ | |
380 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer, PyBUF_CONTIG) | |
381 cdef uint32_t input_buffer_length = buffer_as_buffer.len | |
382 cdef c_core.MojoHandle* input_handles = NULL | |
383 cdef uint32_t input_handles_length = 0 | |
384 cdef _ScopedMemory handles_alloc = None | |
385 if max_number_of_handles > 0: | |
386 input_handles_length = max_number_of_handles | |
387 handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) * | |
388 input_handles_length) | |
389 input_handles = <c_core.MojoHandle*>handles_alloc.memory | |
390 cdef res = c_core.MojoReadMessage(self._mojo_handle, | |
391 buffer_as_buffer.buf, | |
392 &input_buffer_length, | |
393 input_handles, | |
394 &input_handles_length, | |
395 flags) | |
396 if res == c_core.MOJO_RESULT_RESOURCE_EXHAUSTED: | |
397 return (res, None, (input_buffer_length, input_handles_length)) | |
398 if res == c_core.MOJO_RESULT_OK: | |
399 returned_handles = [Handle(input_handles[i]) | |
400 for i in xrange(input_handles_length)] | |
401 return (res, | |
402 (_slice_buffer(buffer, input_buffer_length), returned_handles), | |
403 None) | |
404 return (res, None, None) | |
405 | |
406 def write_data(self, buffer=None, flags=WRITE_DATA_FLAG_NONE): | |
407 """ | |
408 Writes the given data to the data pipe producer. | |
409 | |
410 This method can only be used on a producer handle obtained from | |
411 |DataPipe()|. | |
412 | |
413 This method returns a tuple (code, num_bytes). | |
414 - If code is RESULT_OK, num_bytes is the number of written bytes. | |
415 - Otherwise, num_bytes is None. | |
416 | |
417 See mojo/public/c/system/data_pipe.h | |
418 """ | |
419 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) | |
420 cdef uint32_t input_buffer_length = buffer_as_buffer.len | |
421 cdef c_core.MojoResult res = c_core.MojoWriteData(self._mojo_handle, | |
422 buffer_as_buffer.buf, | |
423 &input_buffer_length, | |
424 flags) | |
425 if res == c_core.MOJO_RESULT_OK: | |
426 return (res, input_buffer_length) | |
427 return (res, None) | |
428 | |
429 def begin_write_data(self, | |
430 min_size=None, | |
431 flags=WRITE_DATA_FLAG_NONE): | |
432 """ | |
433 Begins a two-phase write to the data pipe producer. | |
434 | |
435 This method can only be used on a producer handle obtained from | |
436 |DataPipe()|. | |
437 | |
438 This method returns a tuple (code, two_phase_buffer). | |
439 - If code is RESULT_OK, two_phase_buffer is a writable | |
440 DataPipeTwoPhaseBuffer | |
441 - Otherwise, two_phase_buffer is None. | |
442 | |
443 See mojo/public/c/system/data_pipe.h | |
444 """ | |
445 cdef void* out_buffer | |
446 cdef uint32_t out_size = 0 | |
447 if min_size: | |
448 flags |= c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE | |
449 out_size = min_size | |
450 cdef c_core.MojoResult res = c_core.MojoBeginWriteData(self._mojo_handle, | |
451 &out_buffer, | |
452 &out_size, | |
453 flags) | |
454 if res != c_core.MOJO_RESULT_OK: | |
455 return (res, None) | |
456 cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) | |
457 view_buffer.wrap(out_buffer, out_size, read_only=False) | |
458 return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), False)) | |
459 | |
460 def read_data(self, buffer=None, flags=READ_DATA_FLAG_NONE): | |
461 """Reads data from the data pipe consumer. | |
462 | |
463 This method can only be used on a consumer handle obtained from | |
464 |DataPipe()|. | |
465 | |
466 This method returns a tuple (code, buffer) | |
467 - if code is RESULT_OK, buffer will be a view of the input buffer with the | |
468 read data. | |
469 - otherwise, buffer will be None. | |
470 | |
471 See mojo/public/c/system/data_pipe.h | |
472 """ | |
473 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) | |
474 cdef uint32_t input_buffer_length = buffer_as_buffer.len | |
475 cdef c_core.MojoResult res = c_core.MojoReadData(self._mojo_handle, | |
476 buffer_as_buffer.buf, | |
477 &input_buffer_length, | |
478 flags) | |
479 if res == c_core.MOJO_RESULT_OK: | |
480 return (res, _slice_buffer(buffer, input_buffer_length)) | |
481 return (res, None) | |
482 | |
483 def query_data(self, flags=READ_DATA_FLAG_NONE): | |
484 """Queries the amount of data available on the data pipe consumer. | |
485 | |
486 This method can only be used on a consumer handle obtained from | |
487 |DataPipe()|. | |
488 | |
489 This method returns a tuple (code, num_bytes) | |
490 - if code is RESULT_OK, num_bytes will be the number of bytes available on | |
491 the data pipe consumer. | |
492 - otherwise, num_bytes will be None. | |
493 | |
494 See mojo/public/c/system/data_pipe.h | |
495 """ | |
496 cdef uint32_t num_bytes = 0 | |
497 cdef c_core.MojoResult res = c_core.MojoReadData( | |
498 self._mojo_handle, | |
499 NULL, | |
500 &num_bytes, | |
501 flags|c_core.MOJO_READ_DATA_FLAG_QUERY) | |
502 return (res, num_bytes) | |
503 | |
504 def begin_read_data(self, min_size = None, flags=READ_DATA_FLAG_NONE): | |
pkl (ping after 24h if needed)
2014/08/21 09:32:47
style: no space around =
qsr
2014/08/21 12:10:05
Done.
| |
505 """ | |
506 Begins a two-phase read to the data pipe consumer. | |
507 | |
508 This method can only be used on a consumer handle obtained from | |
509 |DataPipe()|. | |
510 | |
511 This method returns a tuple (code, two_phase_buffer). | |
512 - If code is RESULT_OK, two_phase_buffer is a readable | |
513 DataPipeTwoPhaseBuffer | |
514 - Otherwise, two_phase_buffer is None. | |
515 | |
516 See mojo/public/c/system/data_pipe.h | |
517 """ | |
518 cdef const void* out_buffer | |
519 cdef uint32_t out_size = 0 | |
520 if min_size: | |
521 flags |= c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE | |
522 out_size = min_size | |
523 cdef c_core.MojoResult res = c_core.MojoBeginReadData(self._mojo_handle, | |
524 &out_buffer, | |
525 &out_size, | |
526 flags) | |
527 if res != c_core.MOJO_RESULT_OK: | |
528 return (res, None) | |
529 cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) | |
530 view_buffer.wrap(out_buffer, out_size, read_only=True) | |
531 return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), True)) | |
532 | |
533 def duplicate(self, options=None): | |
534 """Duplicate the shared buffer handle. | |
535 | |
536 This method can only be used on a handle obtained from | |
537 |create_shared_buffer()| or |duplicate()|. | |
538 | |
539 See mojo/public/c/system/buffer.h | |
540 """ | |
541 cdef c_core.MojoDuplicateBufferHandleOptions coptions | |
542 cdef c_core.MojoDuplicateBufferHandleOptions* coptions_ptr = NULL | |
543 cdef c_core.MojoHandle cnew_handle = c_core.MOJO_HANDLE_INVALID | |
544 if options: | |
545 coptions.struct_size = sizeof(c_core.MojoDuplicateBufferHandleOptions) | |
546 coptions.flags = options.flags | |
547 coptions_ptr = &coptions | |
548 cdef c_core.MojoResult result = c_core.MojoDuplicateBufferHandle( | |
549 self._mojo_handle, coptions_ptr, &cnew_handle) | |
550 new_handle = Handle(cnew_handle) | |
551 if result != c_core.MOJO_RESULT_OK: | |
552 raise MojoException(result) | |
553 return new_handle | |
554 | |
555 def map(self, offset, num_bytes, flags=MAP_BUFFER_FLAG_NONE): | |
556 """Maps the part (at offset |offset| of length |num_bytes|) of the buffer. | |
557 | |
558 This method can only be used on a handle obtained from | |
559 |create_shared_buffer()| or |duplicate()|. | |
560 | |
561 This method returns a tuple (code, mapped_buffer). | |
562 - If code is RESULT_OK, mapped_buffer is a readable/writable | |
563 MappedBuffer | |
564 - Otherwise, mapped_buffer is None. | |
565 | |
566 See mojo/public/c/system/buffer.h | |
567 """ | |
568 cdef void* buffer | |
569 res = c_core.MojoMapBuffer(self._mojo_handle, | |
570 offset, | |
571 num_bytes, | |
572 &buffer, | |
573 flags) | |
574 if res != c_core.MOJO_RESULT_OK: | |
575 return (res, None) | |
576 cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) | |
577 view_buffer.wrap(buffer, num_bytes, read_only=False) | |
578 return (res, MappedBuffer(self, | |
579 memoryview(view_buffer), | |
580 lambda: c_core.MojoUnmapBuffer(buffer))) | |
581 | |
582 class CreateMessagePipeOptions(object): | |
583 """Options for creating a message pipe. | |
584 | |
585 See mojo/public/c/system/message_pipe.h | |
586 """ | |
587 FLAG_NONE = c_core.MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE | |
588 | |
589 def __init__(self): | |
590 self.flags = CreateMessagePipeOptions.FLAG_NONE | |
591 | |
592 class MessagePipe(object): | |
593 """Creates a message pipe. | |
594 | |
595 The two ends of the message pipe are accessible with the members handle0 and | |
596 handle1. | |
597 | |
598 See mojo/public/c/system/message_pipe.h | |
599 """ | |
600 def __init__(self, options=None): | |
601 cdef c_core.MojoCreateMessagePipeOptions coptions | |
602 cdef c_core.MojoCreateMessagePipeOptions* coptions_ptr = NULL | |
603 cdef c_core.MojoHandle chandle0 = c_core.MOJO_HANDLE_INVALID | |
604 cdef c_core.MojoHandle chandle1 = c_core.MOJO_HANDLE_INVALID | |
605 if options: | |
606 coptions.struct_size = sizeof(c_core.MojoCreateMessagePipeOptions) | |
607 coptions.flags = options.flags | |
608 coptions_ptr = &coptions | |
609 cdef c_core.MojoResult result = c_core.MojoCreateMessagePipe(coptions_ptr, | |
610 &chandle0, | |
611 &chandle1) | |
612 self.handle0 = Handle(chandle0) | |
613 self.handle1 = Handle(chandle1) | |
614 if result != c_core.MOJO_RESULT_OK: | |
615 raise c_core.MojoException(result) | |
616 | |
617 | |
618 class CreateDataPipeOptions(object): | |
619 """Options for creating a data pipe. | |
620 | |
621 See mojo/public/c/system/data_pipe.h | |
622 """ | |
623 FLAG_NONE = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE | |
624 FLAG_MAY_DISCARD = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD | |
625 | |
626 def __init__(self): | |
627 self.flags = CreateDataPipeOptions.FLAG_NONE | |
628 self.element_num_bytes = 1 | |
629 self.capacity_num_bytes = 0 | |
630 | |
631 class DataPipe(object): | |
632 """Creates a data pipe. | |
633 | |
634 The producer end of the data pipe is accessible with the member | |
635 producer_handle and the consumer end of the data pipe is accessible with the | |
636 member cconsumer_handle. | |
637 | |
638 See mojo/public/c/system/data_pipe.h | |
639 """ | |
640 def __init__(self, options=None): | |
641 cdef c_core.MojoCreateDataPipeOptions coptions | |
642 cdef c_core.MojoCreateDataPipeOptions* coptions_ptr = NULL | |
643 cdef c_core.MojoHandle cproducer_handle = c_core.MOJO_HANDLE_INVALID | |
644 cdef c_core.MojoHandle cconsumer_handle = c_core.MOJO_HANDLE_INVALID | |
645 if options: | |
646 coptions.struct_size = sizeof(c_core.MojoCreateDataPipeOptions) | |
647 coptions.flags = options.flags | |
648 coptions.element_num_bytes = options.element_num_bytes | |
649 coptions.capacity_num_bytes = options.capacity_num_bytes | |
650 coptions_ptr = &coptions | |
651 cdef c_core.MojoResult result = c_core.MojoCreateDataPipe(coptions_ptr, | |
652 &cproducer_handle, | |
653 &cconsumer_handle) | |
654 self.producer_handle = Handle(cproducer_handle) | |
655 self.consumer_handle = Handle(cconsumer_handle) | |
656 if result != c_core.MOJO_RESULT_OK: | |
657 raise MojoException(result) | |
658 | |
659 class CreateSharedBufferOptions(object): | |
660 """Options for creating a shared buffer. | |
661 | |
662 See mojo/public/c/system/buffer.h | |
663 """ | |
664 FLAG_NONE = c_core.MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE | |
665 | |
666 def __init__(self): | |
667 self.flags = CreateSharedBufferOptions.FLAG_NONE | |
668 | |
669 def create_shared_buffer(num_bytes, options=None): | |
670 """Creates a buffer of size |num_bytes| bytes that can be shared. | |
671 | |
672 See mojo/public/c/system/buffer.h | |
673 """ | |
674 cdef c_core.MojoCreateSharedBufferOptions coptions | |
675 cdef c_core.MojoCreateSharedBufferOptions* coptions_ptr = NULL | |
676 cdef c_core.MojoHandle chandle = c_core.MOJO_HANDLE_INVALID | |
677 if options: | |
678 coptions.struct_size = sizeof(c_core.MojoCreateSharedBufferOptions) | |
679 coptions.flags = options.flags | |
680 coptions_ptr = &coptions | |
681 cdef c_core.MojoResult result = c_core.MojoCreateSharedBuffer(coptions_ptr, | |
682 num_bytes, | |
683 &chandle) | |
684 handle = Handle(chandle) | |
685 if result != c_core.MOJO_RESULT_OK: | |
686 raise MojoException(result) | |
687 return handle | |
688 | |
689 class DuplicateSharedBufferOptions(object): | |
690 """Options for duplicating a shared buffer. | |
691 | |
692 See mojo/public/c/system/buffer.h | |
693 """ | |
694 FLAG_NONE = c_core.MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE | |
695 | |
696 def __init__(self): | |
697 self.flags = DuplicateSharedBufferOptions.FLAG_NONE | |
OLD | NEW |