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.
5 # distutils language = c++
8 cimport c_export
# needed so the init function gets exported
12 from cpython
.buffer cimport PyBUF_CONTIG
13 from cpython
.buffer cimport PyBUF_CONTIG_RO
14 from cpython
.buffer cimport Py_buffer
15 from cpython
.buffer cimport PyBuffer_FillInfo
16 from cpython
.buffer cimport PyBuffer_Release
17 from cpython
.buffer cimport PyObject_GetBuffer
18 from cpython
.mem cimport PyMem_Malloc
, PyMem_Free
19 from cpython
.object cimport Py_EQ
, Py_NE
20 from libc
.stdint cimport int32_t
, int64_t
, uint32_t
, uint64_t
, uintptr_t
25 import mojo_system_impl
27 def SetSystemThunks
(system_thunks_as_object
):
28 """Bind the basic Mojo Core functions.
30 This should only be used by the embedder.
32 cdef const c_thunks
.MojoSystemThunks
* system_thunks
= (
33 <const c_thunks
.MojoSystemThunks
*><uintptr_t
>system_thunks_as_object
)
34 c_thunks
.MojoSetSystemThunks
(system_thunks
)
36 HANDLE_INVALID
= c_core
.MOJO_HANDLE_INVALID
37 RESULT_OK
= c_core
.MOJO_RESULT_OK
38 RESULT_CANCELLED
= c_core
.MOJO_RESULT_CANCELLED
39 RESULT_UNKNOWN
= c_core
.MOJO_RESULT_UNKNOWN
40 RESULT_INVALID_ARGUMENT
= c_core
.MOJO_RESULT_INVALID_ARGUMENT
41 RESULT_DEADLINE_EXCEEDED
= c_core
.MOJO_RESULT_DEADLINE_EXCEEDED
42 RESULT_NOT_FOUND
= c_core
.MOJO_RESULT_NOT_FOUND
43 RESULT_ALREADY_EXISTS
= c_core
.MOJO_RESULT_ALREADY_EXISTS
44 RESULT_PERMISSION_DENIED
= c_core
.MOJO_RESULT_PERMISSION_DENIED
45 RESULT_RESOURCE_EXHAUSTED
= c_core
.MOJO_RESULT_RESOURCE_EXHAUSTED
46 RESULT_FAILED_PRECONDITION
= c_core
.MOJO_RESULT_FAILED_PRECONDITION
47 RESULT_ABORTED
= c_core
.MOJO_RESULT_ABORTED
48 RESULT_OUT_OF_RANGE
= c_core
.MOJO_RESULT_OUT_OF_RANGE
49 RESULT_UNIMPLEMENTED
= c_core
.MOJO_RESULT_UNIMPLEMENTED
50 RESULT_INTERNAL
= c_core
.MOJO_RESULT_INTERNAL
51 RESULT_UNAVAILABLE
= c_core
.MOJO_RESULT_UNAVAILABLE
52 RESULT_DATA_LOSS
= c_core
.MOJO_RESULT_DATA_LOSS
53 RESULT_BUSY
= c_core
.MOJO_RESULT_BUSY
54 RESULT_SHOULD_WAIT
= c_core
.MOJO_RESULT_SHOULD_WAIT
55 DEADLINE_INDEFINITE
= c_core
.MOJO_DEADLINE_INDEFINITE
56 HANDLE_SIGNAL_NONE
= c_core
.MOJO_HANDLE_SIGNAL_NONE
57 HANDLE_SIGNAL_READABLE
= c_core
.MOJO_HANDLE_SIGNAL_READABLE
58 HANDLE_SIGNAL_WRITABLE
= c_core
.MOJO_HANDLE_SIGNAL_WRITABLE
59 HANDLE_SIGNAL_PEER_CLOSED
= c_core
.MOJO_HANDLE_SIGNAL_PEER_CLOSED
60 WRITE_MESSAGE_FLAG_NONE
= c_core
.MOJO_WRITE_MESSAGE_FLAG_NONE
61 READ_MESSAGE_FLAG_NONE
= c_core
.MOJO_READ_MESSAGE_FLAG_NONE
62 READ_MESSAGE_FLAG_MAY_DISCARD
= c_core
.MOJO_READ_MESSAGE_FLAG_MAY_DISCARD
63 WRITE_DATA_FLAG_NONE
= c_core
.MOJO_WRITE_DATA_FLAG_NONE
64 WRITE_DATA_FLAG_ALL_OR_NONE
= c_core
.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
65 READ_DATA_FLAG_NONE
= c_core
.MOJO_READ_DATA_FLAG_NONE
66 READ_DATA_FLAG_ALL_OR_NONE
= c_core
.MOJO_READ_DATA_FLAG_ALL_OR_NONE
67 READ_DATA_FLAG_DISCARD
= c_core
.MOJO_READ_DATA_FLAG_DISCARD
68 READ_DATA_FLAG_QUERY
= c_core
.MOJO_READ_DATA_FLAG_QUERY
69 READ_DATA_FLAG_PEEK
= c_core
.MOJO_READ_DATA_FLAG_PEEK
70 MAP_BUFFER_FLAG_NONE
= c_core
.MOJO_MAP_BUFFER_FLAG_NONE
72 _WAITMANY_NO_SIGNAL_STATE_ERRORS
= [RESULT_INVALID_ARGUMENT
,
73 RESULT_RESOURCE_EXHAUSTED
]
75 def GetTimeTicksNow
():
76 """Monotonically increasing tick count representing "right now."
78 See mojo/public/c/system/functions.h
80 return c_core
.MojoGetTimeTicksNow
()
82 cdef class _ScopedMemory
:
83 """Allocate memory at creation, and deallocate it at destruction."""
85 def __init__
(self, size
):
86 self.memory
= PyMem_Malloc
(size
)
88 def __dealloc__
(self):
89 PyMem_Free
(self.memory
)
91 cdef class _ScopedBuffer
:
92 """Retrieve pointer to a buffer a creation, and release it at destruction.
98 def __init__
(self, obj
, flags
=PyBUF_CONTIG_RO
):
100 if PyObject_GetBuffer
(obj
, &self._buf
, flags
) < 0:
101 raise TypeError('Unable to read buffer.')
102 self.buf
= self._buf
.buf
103 self.len = self._buf
.len
108 def __dealloc__
(self):
110 PyBuffer_Release
(&self._buf
)
112 def _SliceBuffer
(buffer
, size
):
113 """Slice the given buffer, reducing it to the given size.
115 Return None if None is passed in.
121 cdef class _NativeMemoryView
(object):
122 """Create a python buffer wrapping the given memory.
124 Will also retain the given handle until this object is deallocated.
132 def __init__
(self, handle
):
133 self._handle
= handle
138 self._read_only
= True
139 self._wrapped
= False
145 """Makes this buffer wraps the given memory.
147 Must be called before using this buffer, and must only be called once.
149 assert not self._wrapped
151 self._memory
= <void*>memory
153 self._read_only
= read_only
155 # buffer interface (PEP 3118)
156 def __getbuffer__
(self, Py_buffer
*view
, int flags
):
160 PyBuffer_FillInfo
(view
,
167 def __releasebuffer__
(self, Py_buffer
*view
):
171 # legacy buffer interface
172 def __getsegcount__
(self, Py_ssize_t
*sizes
):
175 sizes
[0] = self._size
178 def __getreadbuffer__
(self, Py_ssize_t index
, void **data
):
181 raise SystemError('Index out of bounds: %d' % index
)
182 data
[0] = self._memory
185 def __getwritebuffer__
(self, Py_ssize_t index
, void **data
):
188 raise SystemError('Index out of bounds: %d' % index
)
190 raise TypeError('Buffer is read-only.')
191 data
[0] = self._memory
194 class MojoException
(Exception):
195 """Exception wrapping a mojo result error code."""
197 def __init__
(self, mojo_result
):
198 self.mojo_result
= mojo_result
200 def WaitMany
(handles_and_signals
, deadline
):
201 """Waits on a list of handles.
204 handles_and_signals: list of tuples of handle and signal.
206 See mojo/public/c/system/functions.h
208 cdef uint32_t length
= len(handles_and_signals
)
209 cdef uint32_t result_index
= <uint32_t
>(-1)
211 cdef _ScopedMemory handles_alloc
= _ScopedMemory
(
212 sizeof(c_core
.MojoHandle
) * length
)
213 cdef _ScopedMemory signals_alloc
= _ScopedMemory
(
214 sizeof(c_core
.MojoHandleSignals
) * length
)
215 cdef _ScopedMemory states_alloc
= _ScopedMemory
(
216 sizeof(c_core
.MojoHandleSignalsState
) * length
)
217 cdef c_core
.MojoHandle
* handles
= <c_core
.MojoHandle
*>handles_alloc
.memory
218 cdef c_core
.MojoHandleSignals
* signals
= (
219 <c_core
.MojoHandleSignals
*>signals_alloc
.memory
)
220 cdef c_core
.MojoHandleSignalsState
* states
= (
221 <c_core
.MojoHandleSignalsState
*>states_alloc
.memory
)
223 for (h
, s
) in handles_and_signals
:
224 handles
[index
] = (<Handle?
>h
)._mojo_handle
227 cdef c_core
.MojoResult result
= c_core
.MOJO_RESULT_OK
228 cdef c_core
.MojoDeadline cdeadline
= deadline
230 result
= c_core
.MojoWaitMany
(handles
, signals
, length
, cdeadline
,
231 &result_index
, states
)
233 returned_result_index
= None
234 if result_index
!= <uint32_t
>(-1):
235 returned_result_index
= result_index
237 returned_states
= None
238 if result
not in _WAITMANY_NO_SIGNAL_STATE_ERRORS
:
239 returned_states
= [(states
[i
].satisfied_signals
,
240 states
[i
].satisfiable_signals
) for i
in xrange(length
)]
242 return (result
, returned_result_index
, returned_states
)
245 cdef class DataPipeTwoPhaseBuffer
(object):
246 """Return value for two phases read and write.
248 The buffer field contains the python buffer where data can be read or written.
249 When done with the buffer, the |end| method must be called with the number of
250 bytes read or written.
257 def __init__
(self, handle
, buffer
, read
=True
):
258 self._buffer
= buffer
259 self._handle
= handle
262 def End
(self, num_bytes
):
264 cdef c_core
.MojoResult result
266 result
= c_core
.MojoEndReadData
(self._handle
._mojo_handle
, num_bytes
)
268 result
= c_core
.MojoEndWriteData
(self._handle
._mojo_handle
, num_bytes
)
276 def __dealloc__
(self):
277 assert not self._buffer
279 cdef class MappedBuffer
(object):
280 """Return value for the |map| operation on shared buffer handles.
282 The buffer field contains the python buffer where data can be read or written.
283 When done with the buffer, the |unmap| method must be called.
290 def __init__
(self, handle
, buffer
, cleanup
):
291 self._buffer
= buffer
292 self._handle
= handle
293 self._cleanup
= cleanup
297 cdef c_core
.MojoResult result
= self._cleanup
()
306 def __dealloc__
(self):
310 cdef class Handle
(object):
313 cdef c_core
.MojoHandle _mojo_handle
315 def __init__
(self, mojo_handle
=c_core
.MOJO_HANDLE_INVALID
):
316 self._mojo_handle
= mojo_handle
318 def _Invalidate
(self):
319 """Invalidate the current handle.
321 The close operation is not called. It is the responsability of the caller to
322 ensure that the handle is not leaked.
324 self._mojo_handle
= c_core
.MOJO_HANDLE_INVALID
326 def __richcmp__
(self, other
, op
):
327 if op
!= Py_EQ
and op
!= Py_NE
:
328 raise TypeError('Handle is not ordered')
330 if type(self) is not type(other
):
331 equality
= id(self) == id(other
)
333 equality
= (<Handle
>self)._mojo_handle
== (<Handle
>other
)._mojo_handle
340 """Returns whether this handle is valid."""
341 return self._mojo_handle
!= c_core
.MOJO_HANDLE_INVALID
344 """Closes this handle.
346 See mojo/public/c/system/functions.h
348 cdef c_core
.MojoResult result
= c_core
.MOJO_RESULT_OK
350 result
= c_core
.MojoClose
(self._mojo_handle
)
354 def __dealloc__
(self):
357 def Wait
(self, signals
, deadline
):
358 """Waits on the given handle.
360 See mojo/public/c/system/functions.h
362 cdef c_core
.MojoHandle handle
= self._mojo_handle
363 cdef c_core
.MojoHandleSignals csignals
= signals
364 cdef c_core
.MojoDeadline cdeadline
= deadline
365 cdef c_core
.MojoHandleSignalsState signal_states
366 cdef c_core
.MojoResult result
368 result
= c_core
.MojoWait
(handle
, csignals
, cdeadline
, &signal_states
)
370 returned_states
= None
371 if result
not in _WAITMANY_NO_SIGNAL_STATE_ERRORS
:
372 returned_states
= (signal_states
.satisfied_signals
,
373 signal_states
.satisfiable_signals
)
375 return (result
, returned_states
)
377 def AsyncWait
(self, signals
, deadline
, callback
):
378 cdef c_core
.MojoHandle handle
= self._mojo_handle
379 cdef c_core
.MojoHandleSignals csignals
= signals
380 cdef c_core
.MojoDeadline cdeadline
= deadline
381 wait_id
= _ASYNC_WAITER
.AsyncWait
(
387 _ASYNC_WAITER
.CancelWait
(wait_id
)
390 def WriteMessage
(self,
393 flags
=WRITE_MESSAGE_FLAG_NONE
):
394 """Writes a message to the message pipe.
396 This method can only be used on a handle obtained from |MessagePipe()|.
398 See mojo/public/c/system/message_pipe.h
400 cdef _ScopedBuffer buffer_as_buffer
= _ScopedBuffer
(buffer
)
401 cdef uint32_t input_buffer_length
= buffer_as_buffer
.len
402 cdef c_core
.MojoHandle
* input_handles
= NULL
403 cdef uint32_t input_handles_length
= 0
404 cdef _ScopedMemory handles_alloc
= None
406 input_handles_length
= len(handles
)
407 handles_alloc
= _ScopedMemory
(sizeof(c_core
.MojoHandle
) *
408 input_handles_length
)
409 input_handles
= <c_core
.MojoHandle
*>handles_alloc
.memory
410 for i
in xrange(input_handles_length
):
411 input_handles
[i
] = (<Handle?
>handles
[i
])._mojo_handle
412 cdef c_core
.MojoResult res
= c_core
.MojoWriteMessage
(self._mojo_handle
,
413 buffer_as_buffer
.buf
,
416 input_handles_length
,
418 if res
== c_core
.MOJO_RESULT_OK
and handles
:
419 # Handles have been transferred. Let's invalidate those.
420 for handle
in handles
:
424 def ReadMessage
(self,
426 max_number_of_handles
=0,
427 flags
=READ_MESSAGE_FLAG_NONE
):
428 """Reads a message from the message pipe.
430 This method can only be used on a handle obtained from |MessagePipe()|.
432 This method returns a triplet of value (code, data, sizes):
433 - if code is RESULT_OK, sizes will be None, and data will be a pair of
434 (buffer, handles) where buffer is a view of the input buffer with the read
435 data, and handles is a list of received handles.
436 - if code is RESULT_RESOURCE_EXHAUSTED, data will be None and sizes will be
437 a pair of (buffer_size, handles_size) where buffer_size is the size of the
438 next message data and handles_size is the number of handles in the next
440 - if code is any other value, data and sizes will be None.
442 See mojo/public/c/system/message_pipe.h
444 cdef _ScopedBuffer buffer_as_buffer
= _ScopedBuffer
(buffer
, PyBUF_CONTIG
)
445 cdef uint32_t input_buffer_length
= buffer_as_buffer
.len
446 cdef c_core
.MojoHandle
* input_handles
= NULL
447 cdef uint32_t input_handles_length
= 0
448 cdef _ScopedMemory handles_alloc
= None
449 if max_number_of_handles
> 0:
450 input_handles_length
= max_number_of_handles
451 handles_alloc
= _ScopedMemory
(sizeof(c_core
.MojoHandle
) *
452 input_handles_length
)
453 input_handles
= <c_core
.MojoHandle
*>handles_alloc
.memory
454 cdef res
= c_core
.MojoReadMessage
(self._mojo_handle
,
455 buffer_as_buffer
.buf
,
456 &input_buffer_length
,
458 &input_handles_length
,
460 if res
== c_core
.MOJO_RESULT_RESOURCE_EXHAUSTED
:
461 return (res
, None
, (input_buffer_length
, input_handles_length
))
462 if res
== c_core
.MOJO_RESULT_OK
:
463 returned_handles
= [Handle
(input_handles
[i
])
464 for i
in xrange(input_handles_length
)]
466 (_SliceBuffer
(buffer
, input_buffer_length
), returned_handles
),
468 return (res
, None
, None
)
470 def WriteData
(self, buffer
=None
, flags
=WRITE_DATA_FLAG_NONE
):
472 Writes the given data to the data pipe producer.
474 This method can only be used on a producer handle obtained from
477 This method returns a tuple (code, num_bytes).
478 - If code is RESULT_OK, num_bytes is the number of written bytes.
479 - Otherwise, num_bytes is None.
481 See mojo/public/c/system/data_pipe.h
483 cdef _ScopedBuffer buffer_as_buffer
= _ScopedBuffer
(buffer
)
484 cdef uint32_t input_buffer_length
= buffer_as_buffer
.len
485 cdef c_core
.MojoResult res
= c_core
.MojoWriteData
(self._mojo_handle
,
486 buffer_as_buffer
.buf
,
487 &input_buffer_length
,
489 if res
== c_core
.MOJO_RESULT_OK
:
490 return (res
, input_buffer_length
)
493 def BeginWriteData
(self,
495 flags
=WRITE_DATA_FLAG_NONE
):
497 Begins a two-phase write to the data pipe producer.
499 This method can only be used on a producer handle obtained from
502 This method returns a tuple (code, two_phase_buffer).
503 - If code is RESULT_OK, two_phase_buffer is a writable
504 DataPipeTwoPhaseBuffer
505 - Otherwise, two_phase_buffer is None.
507 See mojo/public/c/system/data_pipe.h
509 cdef void* out_buffer
510 cdef uint32_t out_size
= 0
512 flags |
= c_core
.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
514 cdef c_core
.MojoResult res
= c_core
.MojoBeginWriteData
(self._mojo_handle
,
518 if res
!= c_core
.MOJO_RESULT_OK
:
520 cdef _NativeMemoryView view_buffer
= _NativeMemoryView
(self)
521 view_buffer
.Wrap
(out_buffer
, out_size
, read_only
=False
)
522 return (res
, DataPipeTwoPhaseBuffer
(self, memoryview
(view_buffer
), False
))
524 def ReadData
(self, buffer
=None
, flags
=READ_DATA_FLAG_NONE
):
525 """Reads data from the data pipe consumer.
527 This method can only be used on a consumer handle obtained from
530 This method returns a tuple (code, buffer)
531 - if code is RESULT_OK, buffer will be a view of the input buffer with the
533 - otherwise, buffer will be None.
535 See mojo/public/c/system/data_pipe.h
537 cdef _ScopedBuffer buffer_as_buffer
= _ScopedBuffer
(buffer
)
538 cdef uint32_t input_buffer_length
= buffer_as_buffer
.len
539 cdef c_core
.MojoResult res
= c_core
.MojoReadData
(self._mojo_handle
,
540 buffer_as_buffer
.buf
,
541 &input_buffer_length
,
543 if res
== c_core
.MOJO_RESULT_OK
:
544 return (res
, _SliceBuffer
(buffer
, input_buffer_length
))
547 def QueryData
(self, flags
=READ_DATA_FLAG_NONE
):
548 """Queries the amount of data available on the data pipe consumer.
550 This method can only be used on a consumer handle obtained from
553 This method returns a tuple (code, num_bytes)
554 - if code is RESULT_OK, num_bytes will be the number of bytes available on
555 the data pipe consumer.
556 - otherwise, num_bytes will be None.
558 See mojo/public/c/system/data_pipe.h
560 cdef uint32_t num_bytes
= 0
561 cdef c_core
.MojoResult res
= c_core
.MojoReadData
(
565 flags|c_core
.MOJO_READ_DATA_FLAG_QUERY
)
566 return (res
, num_bytes
)
568 def BeginReadData
(self, min_size
=None
, flags
=READ_DATA_FLAG_NONE
):
570 Begins a two-phase read to the data pipe consumer.
572 This method can only be used on a consumer handle obtained from
575 This method returns a tuple (code, two_phase_buffer).
576 - If code is RESULT_OK, two_phase_buffer is a readable
577 DataPipeTwoPhaseBuffer
578 - Otherwise, two_phase_buffer is None.
580 See mojo/public/c/system/data_pipe.h
582 cdef const
void* out_buffer
583 cdef uint32_t out_size
= 0
585 flags |
= c_core
.MOJO_READ_DATA_FLAG_ALL_OR_NONE
587 cdef c_core
.MojoResult res
= c_core
.MojoBeginReadData
(self._mojo_handle
,
591 if res
!= c_core
.MOJO_RESULT_OK
:
593 cdef _NativeMemoryView view_buffer
= _NativeMemoryView
(self)
594 view_buffer
.Wrap
(out_buffer
, out_size
, read_only
=True
)
595 return (res
, DataPipeTwoPhaseBuffer
(self, memoryview
(view_buffer
), True
))
597 def Duplicate
(self, options
=None
):
598 """Duplicate the shared buffer handle.
600 This method can only be used on a handle obtained from
601 |CreateSharedBuffer()| or |Duplicate()|.
603 See mojo/public/c/system/buffer.h
605 cdef c_core
.MojoDuplicateBufferHandleOptions coptions
606 cdef c_core
.MojoDuplicateBufferHandleOptions
* coptions_ptr
= NULL
607 cdef c_core
.MojoHandle cnew_handle
= c_core
.MOJO_HANDLE_INVALID
609 coptions
.struct_size
= sizeof(c_core
.MojoDuplicateBufferHandleOptions
)
610 coptions
.flags
= options
.flags
611 coptions_ptr
= &coptions
612 cdef c_core
.MojoResult result
= c_core
.MojoDuplicateBufferHandle
(
613 self._mojo_handle
, coptions_ptr
, &cnew_handle
)
614 new_handle
= Handle
(cnew_handle
)
615 if result
!= c_core
.MOJO_RESULT_OK
:
616 raise MojoException
(result
)
619 def Map(self, offset
, num_bytes
, flags
=MAP_BUFFER_FLAG_NONE
):
620 """Maps the part (at offset |offset| of length |num_bytes|) of the buffer.
622 This method can only be used on a handle obtained from
623 |CreateSharedBuffer()| or |Duplicate()|.
625 This method returns a tuple (code, mapped_buffer).
626 - If code is RESULT_OK, mapped_buffer is a readable/writable
628 - Otherwise, mapped_buffer is None.
630 See mojo/public/c/system/buffer.h
633 res
= c_core
.MojoMapBuffer
(self._mojo_handle
,
638 if res
!= c_core
.MOJO_RESULT_OK
:
640 cdef _NativeMemoryView view_buffer
= _NativeMemoryView
(self)
641 view_buffer
.Wrap
(buffer
, num_bytes
, read_only
=False
)
642 return (res
, MappedBuffer
(self,
643 memoryview
(view_buffer
),
644 lambda: c_core
.MojoUnmapBuffer
(buffer
)))
646 class CreateMessagePipeOptions
(object):
647 """Options for creating a message pipe.
649 See mojo/public/c/system/message_pipe.h
651 FLAG_NONE
= c_core
.MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE
654 self.flags
= CreateMessagePipeOptions
.FLAG_NONE
656 class MessagePipe
(object):
657 """Creates a message pipe.
659 The two ends of the message pipe are accessible with the members handle0 and
662 See mojo/public/c/system/message_pipe.h
664 def __init__
(self, options
=None
):
665 cdef c_core
.MojoCreateMessagePipeOptions coptions
666 cdef c_core
.MojoCreateMessagePipeOptions
* coptions_ptr
= NULL
667 cdef c_core
.MojoHandle chandle0
= c_core
.MOJO_HANDLE_INVALID
668 cdef c_core
.MojoHandle chandle1
= c_core
.MOJO_HANDLE_INVALID
670 coptions
.struct_size
= sizeof(c_core
.MojoCreateMessagePipeOptions
)
671 coptions
.flags
= options
.flags
672 coptions_ptr
= &coptions
673 cdef c_core
.MojoResult result
= c_core
.MojoCreateMessagePipe
(coptions_ptr
,
676 self.handle0
= Handle
(chandle0
)
677 self.handle1
= Handle
(chandle1
)
678 if result
!= c_core
.MOJO_RESULT_OK
:
679 raise c_core
.MojoException
(result
)
682 class CreateDataPipeOptions
(object):
683 """Options for creating a data pipe.
685 See mojo/public/c/system/data_pipe.h
687 FLAG_NONE
= c_core
.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE
688 FLAG_MAY_DISCARD
= c_core
.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD
691 self.flags
= CreateDataPipeOptions
.FLAG_NONE
692 self.element_num_bytes
= 1
693 self.capacity_num_bytes
= 0
695 class DataPipe
(object):
696 """Creates a data pipe.
698 The producer end of the data pipe is accessible with the member
699 producer_handle and the consumer end of the data pipe is accessible with the
700 member cconsumer_handle.
702 See mojo/public/c/system/data_pipe.h
704 def __init__
(self, options
=None
):
705 cdef c_core
.MojoCreateDataPipeOptions coptions
706 cdef c_core
.MojoCreateDataPipeOptions
* coptions_ptr
= NULL
707 cdef c_core
.MojoHandle cproducer_handle
= c_core
.MOJO_HANDLE_INVALID
708 cdef c_core
.MojoHandle cconsumer_handle
= c_core
.MOJO_HANDLE_INVALID
710 coptions
.struct_size
= sizeof(c_core
.MojoCreateDataPipeOptions
)
711 coptions
.flags
= options
.flags
712 coptions
.element_num_bytes
= options
.element_num_bytes
713 coptions
.capacity_num_bytes
= options
.capacity_num_bytes
714 coptions_ptr
= &coptions
715 cdef c_core
.MojoResult result
= c_core
.MojoCreateDataPipe
(coptions_ptr
,
718 self.producer_handle
= Handle
(cproducer_handle
)
719 self.consumer_handle
= Handle
(cconsumer_handle
)
720 if result
!= c_core
.MOJO_RESULT_OK
:
721 raise MojoException
(result
)
723 class CreateSharedBufferOptions
(object):
724 """Options for creating a shared buffer.
726 See mojo/public/c/system/buffer.h
728 FLAG_NONE
= c_core
.MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE
731 self.flags
= CreateSharedBufferOptions
.FLAG_NONE
733 def CreateSharedBuffer
(num_bytes
, options
=None
):
734 """Creates a buffer of size |num_bytes| bytes that can be shared.
736 See mojo/public/c/system/buffer.h
738 cdef c_core
.MojoCreateSharedBufferOptions coptions
739 cdef c_core
.MojoCreateSharedBufferOptions
* coptions_ptr
= NULL
740 cdef c_core
.MojoHandle chandle
= c_core
.MOJO_HANDLE_INVALID
742 coptions
.struct_size
= sizeof(c_core
.MojoCreateSharedBufferOptions
)
743 coptions
.flags
= options
.flags
744 coptions_ptr
= &coptions
745 cdef c_core
.MojoResult result
= c_core
.MojoCreateSharedBuffer
(coptions_ptr
,
748 handle
= Handle
(chandle
)
749 if result
!= c_core
.MOJO_RESULT_OK
:
750 raise MojoException
(result
)
753 class DuplicateSharedBufferOptions
(object):
754 """Options for duplicating a shared buffer.
756 See mojo/public/c/system/buffer.h
758 FLAG_NONE
= c_core
.MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE
761 self.flags
= DuplicateSharedBufferOptions
.FLAG_NONE
764 # Keeps a thread local weak reference to the current run loop.
765 _RUN_LOOPS
= threading
.local
()
768 class RunLoop
(object):
769 """RunLoop to use when using asynchronous operations on handles."""
772 self.__run_loop
= mojo_system_impl
.RunLoop
()
773 _RUN_LOOPS
.loop
= id(self)
779 """Run the runloop until Quit is called."""
780 return self.__run_loop
.Run
()
782 def RunUntilIdle
(self):
783 """Run the runloop until Quit is called or no operation is waiting."""
784 return self.__run_loop
.RunUntilIdle
()
787 """Quit the runloop."""
788 return self.__run_loop
.Quit
()
790 def PostDelayedTask
(self, runnable
, delay
=0):
792 Post a task on the runloop. This must be called from the thread owning the
795 return self.__run_loop
.PostDelayedTask
(runnable
, delay
)
799 if hasattr(_RUN_LOOPS
, 'loop'):
800 return ctypes
.cast
(_RUN_LOOPS
.loop
, ctypes
.py_object
).value
804 _ASYNC_WAITER
= mojo_system_impl
.AsyncWaiter
()