| Index: mojo/public/python/mojo/system.pyx
|
| diff --git a/mojo/public/python/mojo/system.pyx b/mojo/public/python/mojo/system.pyx
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..80b8dd32f13625d9461aa557ea26db1112f2cafd
|
| --- /dev/null
|
| +++ b/mojo/public/python/mojo/system.pyx
|
| @@ -0,0 +1,696 @@
|
| +# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +# distutils language = c++
|
| +
|
| +cimport c_core
|
| +
|
| +from cpython.buffer cimport PyBUF_CONTIG
|
| +from cpython.buffer cimport PyBUF_CONTIG_RO
|
| +from cpython.buffer cimport Py_buffer
|
| +from cpython.buffer cimport PyBuffer_FillInfo
|
| +from cpython.buffer cimport PyBuffer_Release
|
| +from cpython.buffer cimport PyObject_GetBuffer
|
| +from cpython.mem cimport PyMem_Malloc, PyMem_Free
|
| +from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t
|
| +
|
| +def set_system_thunks(system_thunks_as_object):
|
| + """Bind the basic Mojo Core functions.
|
| +
|
| + This should only be used by the embedder.
|
| + """
|
| + cdef const c_core.MojoSystemThunks* system_thunks = (
|
| + <const c_core.MojoSystemThunks*><uintptr_t>system_thunks_as_object)
|
| + c_core.MojoSetSystemThunks(system_thunks)
|
| +
|
| +HANDLE_INVALID = c_core.MOJO_HANDLE_INVALID
|
| +RESULT_OK = c_core.MOJO_RESULT_OK
|
| +RESULT_CANCELLED = c_core.MOJO_RESULT_CANCELLED
|
| +RESULT_UNKNOWN = c_core.MOJO_RESULT_UNKNOWN
|
| +RESULT_INVALID_ARGUMENT = c_core.MOJO_RESULT_INVALID_ARGUMENT
|
| +RESULT_DEADLINE_EXCEEDED = c_core.MOJO_RESULT_DEADLINE_EXCEEDED
|
| +RESULT_NOT_FOUND = c_core.MOJO_RESULT_NOT_FOUND
|
| +RESULT_ALREADY_EXISTS = c_core.MOJO_RESULT_ALREADY_EXISTS
|
| +RESULT_PERMISSION_DENIED = c_core.MOJO_RESULT_PERMISSION_DENIED
|
| +RESULT_RESOURCE_EXHAUSTED = c_core.MOJO_RESULT_RESOURCE_EXHAUSTED
|
| +RESULT_FAILED_PRECONDITION = c_core.MOJO_RESULT_FAILED_PRECONDITION
|
| +RESULT_ABORTED = c_core.MOJO_RESULT_ABORTED
|
| +RESULT_OUT_OF_RANGE = c_core.MOJO_RESULT_OUT_OF_RANGE
|
| +RESULT_UNIMPLEMENTED = c_core.MOJO_RESULT_UNIMPLEMENTED
|
| +RESULT_INTERNAL = c_core.MOJO_RESULT_INTERNAL
|
| +RESULT_UNAVAILABLE = c_core.MOJO_RESULT_UNAVAILABLE
|
| +RESULT_DATA_LOSS = c_core.MOJO_RESULT_DATA_LOSS
|
| +RESULT_BUSY = c_core.MOJO_RESULT_BUSY
|
| +RESULT_SHOULD_WAIT = c_core.MOJO_RESULT_SHOULD_WAIT
|
| +DEADLINE_INDEFINITE = c_core.MOJO_DEADLINE_INDEFINITE
|
| +HANDLE_SIGNAL_NONE = c_core.MOJO_HANDLE_SIGNAL_NONE
|
| +HANDLE_SIGNAL_READABLE = c_core.MOJO_HANDLE_SIGNAL_READABLE
|
| +HANDLE_SIGNAL_WRITABLE = c_core.MOJO_HANDLE_SIGNAL_WRITABLE
|
| +WRITE_MESSAGE_FLAG_NONE = c_core.MOJO_WRITE_MESSAGE_FLAG_NONE
|
| +READ_MESSAGE_FLAG_NONE = c_core.MOJO_READ_MESSAGE_FLAG_NONE
|
| +READ_MESSAGE_FLAG_MAY_DISCARD = c_core.MOJO_READ_MESSAGE_FLAG_MAY_DISCARD
|
| +WRITE_DATA_FLAG_NONE = c_core.MOJO_WRITE_DATA_FLAG_NONE
|
| +WRITE_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
|
| +READ_DATA_FLAG_NONE = c_core.MOJO_READ_DATA_FLAG_NONE
|
| +READ_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE
|
| +READ_DATA_FLAG_DISCARD = c_core.MOJO_READ_DATA_FLAG_DISCARD
|
| +READ_DATA_FLAG_QUERY = c_core.MOJO_READ_DATA_FLAG_QUERY
|
| +MAP_BUFFER_FLAG_NONE = c_core.MOJO_MAP_BUFFER_FLAG_NONE
|
| +
|
| +def get_time_ticks_now():
|
| + """Monotonically increasing tick count representing "right now."
|
| +
|
| + See mojo/public/c/system/functions.h
|
| + """
|
| + return c_core.MojoGetTimeTicksNow()
|
| +
|
| +cdef class _ScopedMemory:
|
| + """Allocate memory at creation, and deallocate it at destruction."""
|
| + cdef void* memory
|
| + def __init__(self, size):
|
| + self.memory = PyMem_Malloc(size)
|
| +
|
| + def __dealloc__(self):
|
| + PyMem_Free(self.memory)
|
| +
|
| +cdef class _ScopedBuffer:
|
| + """Retrieve pointer to a buffer a creation, and release it at destruction.
|
| + """
|
| + cdef Py_buffer _buf
|
| + cdef void* buf
|
| + cdef Py_ssize_t len
|
| +
|
| + def __init__(self, obj, flags=PyBUF_CONTIG_RO):
|
| + if obj:
|
| + if PyObject_GetBuffer(obj, &self._buf, flags) < 0:
|
| + raise TypeError('Unable to read buffer.')
|
| + self.buf = self._buf.buf
|
| + self.len = self._buf.len
|
| + else:
|
| + self.buf = NULL
|
| + self.len = 0
|
| +
|
| + def __dealloc__(self):
|
| + if self.buf:
|
| + PyBuffer_Release(&self._buf)
|
| +
|
| +def _slice_buffer(buffer, size):
|
| + """Slice the given buffer, reducing it to the given size.
|
| +
|
| + Return None if None is passed in.
|
| + """
|
| + if not buffer:
|
| + return buffer
|
| + return buffer[:size]
|
| +
|
| +cdef class _NativeMemoryView(object):
|
| + """Create a python buffer wrapping the given memory.
|
| +
|
| + Will also retain the given handle until this object is deallocated.
|
| + """
|
| + cdef void* _memory
|
| + cdef uint32_t _size
|
| + cdef char _read_only
|
| + cdef char _wrapped
|
| + cdef object _handle
|
| +
|
| + def __init__(self, handle):
|
| + self._handle = handle
|
| +
|
| + def __cinit__(self):
|
| + self._memory = NULL
|
| + self._size = 0
|
| + self._read_only = True
|
| + self._wrapped = False
|
| +
|
| + cdef wrap(self,
|
| + const void* memory,
|
| + uint32_t size,
|
| + read_only=True):
|
| + """Makes this buffer wraps the given memory.
|
| +
|
| + Must be called before using this buffer, and must only be called once.
|
| + """
|
| + assert not self._wrapped
|
| + self._wrapped = True
|
| + self._memory = <void*>memory
|
| + self._size = size
|
| + self._read_only = read_only
|
| +
|
| + # buffer interface (PEP 3118)
|
| + def __getbuffer__(self, Py_buffer *view, int flags):
|
| + assert self._wrapped
|
| + if view == NULL:
|
| + return
|
| + PyBuffer_FillInfo(view,
|
| + self,
|
| + self._memory,
|
| + self._size,
|
| + self._read_only,
|
| + flags)
|
| +
|
| + def __releasebuffer__(self, Py_buffer *view):
|
| + assert self._wrapped
|
| + pass
|
| +
|
| + # legacy buffer interface
|
| + def __getsegcount__(self, Py_ssize_t *sizes):
|
| + assert self._wrapped
|
| + if sizes != NULL:
|
| + sizes[0] = self._size
|
| + return 1
|
| +
|
| + def __getreadbuffer__(self, Py_ssize_t index, void **data):
|
| + assert self._wrapped
|
| + if index != 0:
|
| + raise SystemError('Index out of bounds: %d' % index)
|
| + data[0] = self._memory
|
| + return self._size
|
| +
|
| + def __getwritebuffer__(self, Py_ssize_t index, void **data):
|
| + assert self._wrapped
|
| + if index != 0:
|
| + raise SystemError('Index out of bounds: %d' % index)
|
| + if self._read_only:
|
| + raise TypeError('Buffer is read-only.')
|
| + data[0] = self._memory
|
| + return self._size
|
| +
|
| +class MojoException(Exception):
|
| + """Exception wrapping a mojo result error code."""
|
| +
|
| + def __init__(self, mojo_result):
|
| + self.mojo_result = mojo_result
|
| +
|
| +def wait_many(handles_and_signals, deadline):
|
| + """Waits on a list of handles.
|
| +
|
| + Args:
|
| + handles_and_signals: list of tuples of handle and signal.
|
| +
|
| + See mojo/public/c/system/functions.h
|
| + """
|
| + cdef uint32_t length = len(handles_and_signals)
|
| + cdef _ScopedMemory handles_alloc = _ScopedMemory(
|
| + sizeof(c_core.MojoHandle) * length)
|
| + cdef _ScopedMemory signals_alloc = _ScopedMemory(
|
| + sizeof(c_core.MojoHandleSignals) * length)
|
| + cdef c_core.MojoHandle* handles = <c_core.MojoHandle*>handles_alloc.memory
|
| + cdef c_core.MojoHandleSignals* signals = (
|
| + <c_core.MojoHandleSignals*>signals_alloc.memory)
|
| + cdef int index = 0
|
| + for (h, s) in handles_and_signals:
|
| + handles[index] = (<Handle?>h)._mojo_handle
|
| + signals[index] = s
|
| + index += 1
|
| + cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK
|
| + cdef c_core.MojoDeadline cdeadline = deadline
|
| + with nogil:
|
| + result = c_core.MojoWaitMany(handles, signals, length, cdeadline)
|
| + return result
|
| +
|
| +cdef class DataPipeTwoPhaseBuffer(object):
|
| + """Return value for two phases read and write.
|
| +
|
| + The buffer field contains the python buffer where data can be read or written.
|
| + When done with the buffer, the |end| method must be called with the number of
|
| + bytes read or written.
|
| + """
|
| +
|
| + cdef object _buffer
|
| + cdef Handle _handle
|
| + cdef char _read
|
| +
|
| + def __init__(self, handle, buffer, read=True):
|
| + self._buffer = buffer
|
| + self._handle = handle
|
| + self._read = read
|
| +
|
| + def end(self, num_bytes):
|
| + self._buffer = None
|
| + cdef c_core.MojoResult result
|
| + if self._read:
|
| + result = c_core.MojoEndReadData(self._handle._mojo_handle, num_bytes)
|
| + else:
|
| + result = c_core.MojoEndWriteData(self._handle._mojo_handle, num_bytes)
|
| + self._handle = None
|
| + return result
|
| +
|
| + @property
|
| + def buffer(self):
|
| + return self._buffer
|
| +
|
| + def __dealloc__(self):
|
| + assert not self._buffer
|
| +
|
| +cdef class MappedBuffer(object):
|
| + """Return value for the |map| operation on shared buffer handles.
|
| +
|
| + The buffer field contains the python buffer where data can be read or written.
|
| + When done with the buffer, the |unmap| method must be called.
|
| + """
|
| +
|
| + cdef object _buffer
|
| + cdef object _handle
|
| + cdef object _cleanup
|
| +
|
| + def __init__(self, handle, buffer, cleanup):
|
| + self._buffer = buffer
|
| + self._handle = handle
|
| + self._cleanup = cleanup
|
| +
|
| + def unmap(self):
|
| + self._buffer = None
|
| + cdef c_core.MojoResult result = self._cleanup()
|
| + self._cleanup = None
|
| + self._handle = None
|
| + return result
|
| +
|
| + @property
|
| + def buffer(self):
|
| + return self._buffer
|
| +
|
| + def __dealloc__(self):
|
| + if self._buffer:
|
| + self.unmap()
|
| +
|
| +cdef class Handle(object):
|
| + """A mojo object."""
|
| +
|
| + cdef c_core.MojoHandle _mojo_handle
|
| +
|
| + def __init__(self, mojo_handle=c_core.MOJO_HANDLE_INVALID):
|
| + self._mojo_handle = mojo_handle
|
| +
|
| + def _invalidate(self):
|
| + """Invalidate the current handle.
|
| +
|
| + The close operation is not called. It is the responsability of the caller to
|
| + ensure that the handle is not leaked.
|
| + """
|
| + self._mojo_handle = c_core.MOJO_HANDLE_INVALID
|
| +
|
| + def is_valid(self):
|
| + """Returns whether this handle is valid."""
|
| + return self._mojo_handle != c_core.MOJO_HANDLE_INVALID
|
| +
|
| + def close(self):
|
| + """Closes this handle.
|
| +
|
| + See mojo/public/c/system/functions.h
|
| + """
|
| + cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK
|
| + if self.is_valid():
|
| + result = c_core.MojoClose(self._mojo_handle)
|
| + self._invalidate()
|
| + return result
|
| +
|
| + def __dealloc__(self):
|
| + self.close()
|
| +
|
| + def wait(self, signals, deadline):
|
| + """Waits on the given handle.
|
| +
|
| + See mojo/public/c/system/functions.h
|
| + """
|
| + cdef c_core.MojoHandle handle = self._mojo_handle
|
| + cdef c_core.MojoHandleSignals csignals = signals
|
| + cdef c_core.MojoDeadline cdeadline = deadline
|
| + cdef c_core.MojoResult result
|
| + with nogil:
|
| + result = c_core.MojoWait(handle, csignals, cdeadline)
|
| + return result
|
| +
|
| + def write_message(self,
|
| + buffer=None,
|
| + handles=None,
|
| + flags=WRITE_MESSAGE_FLAG_NONE):
|
| + """Writes a message to the message pipe.
|
| +
|
| + This method can only be used on a handle obtained from |MessagePipe()|.
|
| +
|
| + See mojo/public/c/system/message_pipe.h
|
| + """
|
| + cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer)
|
| + cdef uint32_t input_buffer_length = buffer_as_buffer.len
|
| + cdef c_core.MojoHandle* input_handles = NULL
|
| + cdef uint32_t input_handles_length = 0
|
| + cdef _ScopedMemory handles_alloc = None
|
| + if handles:
|
| + input_handles_length = len(handles)
|
| + handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) *
|
| + input_handles_length)
|
| + input_handles = <c_core.MojoHandle*>handles_alloc.memory
|
| + for i in xrange(input_handles_length):
|
| + input_handles[i] = (<Handle?>handles[i])._mojo_handle
|
| + cdef c_core.MojoResult res = c_core.MojoWriteMessage(self._mojo_handle,
|
| + buffer_as_buffer.buf,
|
| + input_buffer_length,
|
| + input_handles,
|
| + input_handles_length,
|
| + flags)
|
| + if res == c_core.MOJO_RESULT_OK and handles:
|
| + # Handles have been transferred. Let's invalidate those.
|
| + for handle in handles:
|
| + handle._invalidate()
|
| + return res
|
| +
|
| + def read_message(self,
|
| + buffer=None,
|
| + max_number_of_handles=0,
|
| + flags=READ_MESSAGE_FLAG_NONE):
|
| + """Reads a message from the message pipe.
|
| +
|
| + This method can only be used on a handle obtained from |MessagePipe()|.
|
| +
|
| + This method returns a triplet of value (code, data, sizes):
|
| + - if code is RESULT_OK, sizes will be None, and data will be a pair of
|
| + (buffer, handles) where buffer is a view of the input buffer with the read
|
| + data, and handles is a list of received handles.
|
| + - if code is RESULT_RESOURCE_EXHAUSTED, data will be None and sizes will be
|
| + a pair of (buffer_size, handles_size) where buffer_size is the size of the
|
| + next message data and handles_size is the number of handles in the next
|
| + message.
|
| + - if code is any other value, data and sizes will be None.
|
| +
|
| + See mojo/public/c/system/message_pipe.h
|
| + """
|
| + cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer, PyBUF_CONTIG)
|
| + cdef uint32_t input_buffer_length = buffer_as_buffer.len
|
| + cdef c_core.MojoHandle* input_handles = NULL
|
| + cdef uint32_t input_handles_length = 0
|
| + cdef _ScopedMemory handles_alloc = None
|
| + if max_number_of_handles > 0:
|
| + input_handles_length = max_number_of_handles
|
| + handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) *
|
| + input_handles_length)
|
| + input_handles = <c_core.MojoHandle*>handles_alloc.memory
|
| + cdef res = c_core.MojoReadMessage(self._mojo_handle,
|
| + buffer_as_buffer.buf,
|
| + &input_buffer_length,
|
| + input_handles,
|
| + &input_handles_length,
|
| + flags)
|
| + if res == c_core.MOJO_RESULT_RESOURCE_EXHAUSTED:
|
| + return (res, None, (input_buffer_length, input_handles_length))
|
| + if res == c_core.MOJO_RESULT_OK:
|
| + returned_handles = [Handle(input_handles[i])
|
| + for i in xrange(input_handles_length)]
|
| + return (res,
|
| + (_slice_buffer(buffer, input_buffer_length), returned_handles),
|
| + None)
|
| + return (res, None, None)
|
| +
|
| + def write_data(self, buffer=None, flags=WRITE_DATA_FLAG_NONE):
|
| + """
|
| + Writes the given data to the data pipe producer.
|
| +
|
| + This method can only be used on a producer handle obtained from
|
| + |DataPipe()|.
|
| +
|
| + This method returns a tuple (code, num_bytes).
|
| + - If code is RESULT_OK, num_bytes is the number of written bytes.
|
| + - Otherwise, num_bytes is None.
|
| +
|
| + See mojo/public/c/system/data_pipe.h
|
| + """
|
| + cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer)
|
| + cdef uint32_t input_buffer_length = buffer_as_buffer.len
|
| + cdef c_core.MojoResult res = c_core.MojoWriteData(self._mojo_handle,
|
| + buffer_as_buffer.buf,
|
| + &input_buffer_length,
|
| + flags)
|
| + if res == c_core.MOJO_RESULT_OK:
|
| + return (res, input_buffer_length)
|
| + return (res, None)
|
| +
|
| + def begin_write_data(self,
|
| + min_size=None,
|
| + flags=WRITE_DATA_FLAG_NONE):
|
| + """
|
| + Begins a two-phase write to the data pipe producer.
|
| +
|
| + This method can only be used on a producer handle obtained from
|
| + |DataPipe()|.
|
| +
|
| + This method returns a tuple (code, two_phase_buffer).
|
| + - If code is RESULT_OK, two_phase_buffer is a writable
|
| + DataPipeTwoPhaseBuffer
|
| + - Otherwise, two_phase_buffer is None.
|
| +
|
| + See mojo/public/c/system/data_pipe.h
|
| + """
|
| + cdef void* out_buffer
|
| + cdef uint32_t out_size = 0
|
| + if min_size:
|
| + flags |= c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
|
| + out_size = min_size
|
| + cdef c_core.MojoResult res = c_core.MojoBeginWriteData(self._mojo_handle,
|
| + &out_buffer,
|
| + &out_size,
|
| + flags)
|
| + if res != c_core.MOJO_RESULT_OK:
|
| + return (res, None)
|
| + cdef _NativeMemoryView view_buffer = _NativeMemoryView(self)
|
| + view_buffer.wrap(out_buffer, out_size, read_only=False)
|
| + return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), False))
|
| +
|
| + def read_data(self, buffer=None, flags=READ_DATA_FLAG_NONE):
|
| + """Reads data from the data pipe consumer.
|
| +
|
| + This method can only be used on a consumer handle obtained from
|
| + |DataPipe()|.
|
| +
|
| + This method returns a tuple (code, buffer)
|
| + - if code is RESULT_OK, buffer will be a view of the input buffer with the
|
| + read data.
|
| + - otherwise, buffer will be None.
|
| +
|
| + See mojo/public/c/system/data_pipe.h
|
| + """
|
| + cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer)
|
| + cdef uint32_t input_buffer_length = buffer_as_buffer.len
|
| + cdef c_core.MojoResult res = c_core.MojoReadData(self._mojo_handle,
|
| + buffer_as_buffer.buf,
|
| + &input_buffer_length,
|
| + flags)
|
| + if res == c_core.MOJO_RESULT_OK:
|
| + return (res, _slice_buffer(buffer, input_buffer_length))
|
| + return (res, None)
|
| +
|
| + def query_data(self, flags=READ_DATA_FLAG_NONE):
|
| + """Queries the amount of data available on the data pipe consumer.
|
| +
|
| + This method can only be used on a consumer handle obtained from
|
| + |DataPipe()|.
|
| +
|
| + This method returns a tuple (code, num_bytes)
|
| + - if code is RESULT_OK, num_bytes will be the number of bytes available on
|
| + the data pipe consumer.
|
| + - otherwise, num_bytes will be None.
|
| +
|
| + See mojo/public/c/system/data_pipe.h
|
| + """
|
| + cdef uint32_t num_bytes = 0
|
| + cdef c_core.MojoResult res = c_core.MojoReadData(
|
| + self._mojo_handle,
|
| + NULL,
|
| + &num_bytes,
|
| + flags|c_core.MOJO_READ_DATA_FLAG_QUERY)
|
| + return (res, num_bytes)
|
| +
|
| + def begin_read_data(self, min_size=None, flags=READ_DATA_FLAG_NONE):
|
| + """
|
| + Begins a two-phase read to the data pipe consumer.
|
| +
|
| + This method can only be used on a consumer handle obtained from
|
| + |DataPipe()|.
|
| +
|
| + This method returns a tuple (code, two_phase_buffer).
|
| + - If code is RESULT_OK, two_phase_buffer is a readable
|
| + DataPipeTwoPhaseBuffer
|
| + - Otherwise, two_phase_buffer is None.
|
| +
|
| + See mojo/public/c/system/data_pipe.h
|
| + """
|
| + cdef const void* out_buffer
|
| + cdef uint32_t out_size = 0
|
| + if min_size:
|
| + flags |= c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE
|
| + out_size = min_size
|
| + cdef c_core.MojoResult res = c_core.MojoBeginReadData(self._mojo_handle,
|
| + &out_buffer,
|
| + &out_size,
|
| + flags)
|
| + if res != c_core.MOJO_RESULT_OK:
|
| + return (res, None)
|
| + cdef _NativeMemoryView view_buffer = _NativeMemoryView(self)
|
| + view_buffer.wrap(out_buffer, out_size, read_only=True)
|
| + return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), True))
|
| +
|
| + def duplicate(self, options=None):
|
| + """Duplicate the shared buffer handle.
|
| +
|
| + This method can only be used on a handle obtained from
|
| + |create_shared_buffer()| or |duplicate()|.
|
| +
|
| + See mojo/public/c/system/buffer.h
|
| + """
|
| + cdef c_core.MojoDuplicateBufferHandleOptions coptions
|
| + cdef c_core.MojoDuplicateBufferHandleOptions* coptions_ptr = NULL
|
| + cdef c_core.MojoHandle cnew_handle = c_core.MOJO_HANDLE_INVALID
|
| + if options:
|
| + coptions.struct_size = sizeof(c_core.MojoDuplicateBufferHandleOptions)
|
| + coptions.flags = options.flags
|
| + coptions_ptr = &coptions
|
| + cdef c_core.MojoResult result = c_core.MojoDuplicateBufferHandle(
|
| + self._mojo_handle, coptions_ptr, &cnew_handle)
|
| + new_handle = Handle(cnew_handle)
|
| + if result != c_core.MOJO_RESULT_OK:
|
| + raise MojoException(result)
|
| + return new_handle
|
| +
|
| + def map(self, offset, num_bytes, flags=MAP_BUFFER_FLAG_NONE):
|
| + """Maps the part (at offset |offset| of length |num_bytes|) of the buffer.
|
| +
|
| + This method can only be used on a handle obtained from
|
| + |create_shared_buffer()| or |duplicate()|.
|
| +
|
| + This method returns a tuple (code, mapped_buffer).
|
| + - If code is RESULT_OK, mapped_buffer is a readable/writable
|
| + MappedBuffer
|
| + - Otherwise, mapped_buffer is None.
|
| +
|
| + See mojo/public/c/system/buffer.h
|
| + """
|
| + cdef void* buffer
|
| + res = c_core.MojoMapBuffer(self._mojo_handle,
|
| + offset,
|
| + num_bytes,
|
| + &buffer,
|
| + flags)
|
| + if res != c_core.MOJO_RESULT_OK:
|
| + return (res, None)
|
| + cdef _NativeMemoryView view_buffer = _NativeMemoryView(self)
|
| + view_buffer.wrap(buffer, num_bytes, read_only=False)
|
| + return (res, MappedBuffer(self,
|
| + memoryview(view_buffer),
|
| + lambda: c_core.MojoUnmapBuffer(buffer)))
|
| +
|
| +class CreateMessagePipeOptions(object):
|
| + """Options for creating a message pipe.
|
| +
|
| + See mojo/public/c/system/message_pipe.h
|
| + """
|
| + FLAG_NONE = c_core.MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE
|
| +
|
| + def __init__(self):
|
| + self.flags = CreateMessagePipeOptions.FLAG_NONE
|
| +
|
| +class MessagePipe(object):
|
| + """Creates a message pipe.
|
| +
|
| + The two ends of the message pipe are accessible with the members handle0 and
|
| + handle1.
|
| +
|
| + See mojo/public/c/system/message_pipe.h
|
| + """
|
| + def __init__(self, options=None):
|
| + cdef c_core.MojoCreateMessagePipeOptions coptions
|
| + cdef c_core.MojoCreateMessagePipeOptions* coptions_ptr = NULL
|
| + cdef c_core.MojoHandle chandle0 = c_core.MOJO_HANDLE_INVALID
|
| + cdef c_core.MojoHandle chandle1 = c_core.MOJO_HANDLE_INVALID
|
| + if options:
|
| + coptions.struct_size = sizeof(c_core.MojoCreateMessagePipeOptions)
|
| + coptions.flags = options.flags
|
| + coptions_ptr = &coptions
|
| + cdef c_core.MojoResult result = c_core.MojoCreateMessagePipe(coptions_ptr,
|
| + &chandle0,
|
| + &chandle1)
|
| + self.handle0 = Handle(chandle0)
|
| + self.handle1 = Handle(chandle1)
|
| + if result != c_core.MOJO_RESULT_OK:
|
| + raise c_core.MojoException(result)
|
| +
|
| +
|
| +class CreateDataPipeOptions(object):
|
| + """Options for creating a data pipe.
|
| +
|
| + See mojo/public/c/system/data_pipe.h
|
| + """
|
| + FLAG_NONE = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE
|
| + FLAG_MAY_DISCARD = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD
|
| +
|
| + def __init__(self):
|
| + self.flags = CreateDataPipeOptions.FLAG_NONE
|
| + self.element_num_bytes = 1
|
| + self.capacity_num_bytes = 0
|
| +
|
| +class DataPipe(object):
|
| + """Creates a data pipe.
|
| +
|
| + The producer end of the data pipe is accessible with the member
|
| + producer_handle and the consumer end of the data pipe is accessible with the
|
| + member cconsumer_handle.
|
| +
|
| + See mojo/public/c/system/data_pipe.h
|
| + """
|
| + def __init__(self, options=None):
|
| + cdef c_core.MojoCreateDataPipeOptions coptions
|
| + cdef c_core.MojoCreateDataPipeOptions* coptions_ptr = NULL
|
| + cdef c_core.MojoHandle cproducer_handle = c_core.MOJO_HANDLE_INVALID
|
| + cdef c_core.MojoHandle cconsumer_handle = c_core.MOJO_HANDLE_INVALID
|
| + if options:
|
| + coptions.struct_size = sizeof(c_core.MojoCreateDataPipeOptions)
|
| + coptions.flags = options.flags
|
| + coptions.element_num_bytes = options.element_num_bytes
|
| + coptions.capacity_num_bytes = options.capacity_num_bytes
|
| + coptions_ptr = &coptions
|
| + cdef c_core.MojoResult result = c_core.MojoCreateDataPipe(coptions_ptr,
|
| + &cproducer_handle,
|
| + &cconsumer_handle)
|
| + self.producer_handle = Handle(cproducer_handle)
|
| + self.consumer_handle = Handle(cconsumer_handle)
|
| + if result != c_core.MOJO_RESULT_OK:
|
| + raise MojoException(result)
|
| +
|
| +class CreateSharedBufferOptions(object):
|
| + """Options for creating a shared buffer.
|
| +
|
| + See mojo/public/c/system/buffer.h
|
| + """
|
| + FLAG_NONE = c_core.MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE
|
| +
|
| + def __init__(self):
|
| + self.flags = CreateSharedBufferOptions.FLAG_NONE
|
| +
|
| +def create_shared_buffer(num_bytes, options=None):
|
| + """Creates a buffer of size |num_bytes| bytes that can be shared.
|
| +
|
| + See mojo/public/c/system/buffer.h
|
| + """
|
| + cdef c_core.MojoCreateSharedBufferOptions coptions
|
| + cdef c_core.MojoCreateSharedBufferOptions* coptions_ptr = NULL
|
| + cdef c_core.MojoHandle chandle = c_core.MOJO_HANDLE_INVALID
|
| + if options:
|
| + coptions.struct_size = sizeof(c_core.MojoCreateSharedBufferOptions)
|
| + coptions.flags = options.flags
|
| + coptions_ptr = &coptions
|
| + cdef c_core.MojoResult result = c_core.MojoCreateSharedBuffer(coptions_ptr,
|
| + num_bytes,
|
| + &chandle)
|
| + handle = Handle(chandle)
|
| + if result != c_core.MOJO_RESULT_OK:
|
| + raise MojoException(result)
|
| + return handle
|
| +
|
| +class DuplicateSharedBufferOptions(object):
|
| + """Options for duplicating a shared buffer.
|
| +
|
| + See mojo/public/c/system/buffer.h
|
| + """
|
| + FLAG_NONE = c_core.MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE
|
| +
|
| + def __init__(self):
|
| + self.flags = DuplicateSharedBufferOptions.FLAG_NONE
|
|
|