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.') |
| 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. |
| 100 |
| 101 Return None if None is passed in. |
| 102 """ |
| 103 if not buffer: |
| 104 return buffer |
| 105 return buffer[:size] |
| 106 |
| 107 cdef class _NativeMemoryView(object): |
| 108 """Create a python buffer wrapping the given memory. |
| 109 |
| 110 Will also retain the given handle until this object is deallocated. |
| 111 """ |
| 112 cdef void* _memory |
| 113 cdef uint32_t _size |
| 114 cdef char _read_only |
| 115 cdef char _wrapped |
| 116 cdef object _handle |
| 117 |
| 118 def __init__(self, handle): |
| 119 self._handle = handle |
| 120 |
| 121 def __cinit__(self): |
| 122 self._memory = NULL |
| 123 self._size = 0 |
| 124 self._read_only = True |
| 125 self._wrapped = False |
| 126 |
| 127 cdef wrap(self, |
| 128 const void* memory, |
| 129 uint32_t size, |
| 130 read_only=True): |
| 131 """Makes this buffer wraps the given memory. |
| 132 |
| 133 Must be called before using this buffer, and must only be called once. |
| 134 """ |
| 135 assert not self._wrapped |
| 136 self._wrapped = True |
| 137 self._memory = <void*>memory |
| 138 self._size = size |
| 139 self._read_only = read_only |
| 140 |
| 141 # buffer interface (PEP 3118) |
| 142 def __getbuffer__(self, Py_buffer *view, int flags): |
| 143 assert self._wrapped |
| 144 if view == NULL: |
| 145 return |
| 146 PyBuffer_FillInfo(view, |
| 147 self, |
| 148 self._memory, |
| 149 self._size, |
| 150 self._read_only, |
| 151 flags) |
| 152 |
| 153 def __releasebuffer__(self, Py_buffer *view): |
| 154 assert self._wrapped |
| 155 pass |
| 156 |
| 157 # legacy buffer interface |
| 158 def __getsegcount__(self, Py_ssize_t *sizes): |
| 159 assert self._wrapped |
| 160 if sizes != NULL: |
| 161 sizes[0] = self._size |
| 162 return 1 |
| 163 |
| 164 def __getreadbuffer__(self, Py_ssize_t index, void **data): |
| 165 assert self._wrapped |
| 166 if index != 0: |
| 167 raise SystemError('Index out of bounds: %d' % index) |
| 168 data[0] = self._memory |
| 169 return self._size |
| 170 |
| 171 def __getwritebuffer__(self, Py_ssize_t index, void **data): |
| 172 assert self._wrapped |
| 173 if index != 0: |
| 174 raise SystemError('Index out of bounds: %d' % index) |
| 175 if self._read_only: |
| 176 raise TypeError('Buffer is read-only.') |
| 177 data[0] = self._memory |
| 178 return self._size |
| 179 |
| 180 class MojoException(Exception): |
| 181 """Exception wrapping a mojo result error code.""" |
| 182 |
| 183 def __init__(self, mojo_result): |
| 184 self.mojo_result = mojo_result |
| 185 |
| 186 def wait_many(handles_and_signals, deadline): |
| 187 """Waits on a list of handles. |
| 188 |
| 189 Args: |
| 190 handles_and_signals: list of tuples of handle and signal. |
| 191 |
| 192 See mojo/public/c/system/functions.h |
| 193 """ |
| 194 cdef uint32_t length = len(handles_and_signals) |
| 195 cdef _ScopedMemory handles_alloc = _ScopedMemory( |
| 196 sizeof(c_core.MojoHandle) * length) |
| 197 cdef _ScopedMemory signals_alloc = _ScopedMemory( |
| 198 sizeof(c_core.MojoHandleSignals) * length) |
| 199 cdef c_core.MojoHandle* handles = <c_core.MojoHandle*>handles_alloc.memory |
| 200 cdef c_core.MojoHandleSignals* signals = ( |
| 201 <c_core.MojoHandleSignals*>signals_alloc.memory) |
| 202 cdef int index = 0 |
| 203 for (h, s) in handles_and_signals: |
| 204 handles[index] = (<Handle?>h)._mojo_handle |
| 205 signals[index] = s |
| 206 index += 1 |
| 207 cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK |
| 208 cdef c_core.MojoDeadline cdeadline = deadline |
| 209 with nogil: |
| 210 result = c_core.MojoWaitMany(handles, signals, length, cdeadline) |
| 211 return result |
| 212 |
| 213 cdef class DataPipeTwoPhaseBuffer(object): |
| 214 """Return value for two phases read and write. |
| 215 |
| 216 The buffer field contains the python buffer where data can be read or written. |
| 217 When done with the buffer, the |end| method must be called with the number of |
| 218 bytes read or written. |
| 219 """ |
| 220 |
| 221 cdef object _buffer |
| 222 cdef Handle _handle |
| 223 cdef char _read |
| 224 |
| 225 def __init__(self, handle, buffer, read=True): |
| 226 self._buffer = buffer |
| 227 self._handle = handle |
| 228 self._read = read |
| 229 |
| 230 def end(self, num_bytes): |
| 231 self._buffer = None |
| 232 cdef c_core.MojoResult result |
| 233 if self._read: |
| 234 result = c_core.MojoEndReadData(self._handle._mojo_handle, num_bytes) |
| 235 else: |
| 236 result = c_core.MojoEndWriteData(self._handle._mojo_handle, num_bytes) |
| 237 self._handle = None |
| 238 return result |
| 239 |
| 240 @property |
| 241 def buffer(self): |
| 242 return self._buffer |
| 243 |
| 244 def __dealloc__(self): |
| 245 assert not self._buffer |
| 246 |
| 247 cdef class MappedBuffer(object): |
| 248 """Return value for the |map| operation on shared buffer handles. |
| 249 |
| 250 The buffer field contains the python buffer where data can be read or written. |
| 251 When done with the buffer, the |unmap| method must be called. |
| 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 """Writes a message to the message pipe. |
| 330 |
| 331 This method can only be used on a handle obtained from |MessagePipe()|. |
| 332 |
| 333 See mojo/public/c/system/message_pipe.h |
| 334 """ |
| 335 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) |
| 336 cdef uint32_t input_buffer_length = buffer_as_buffer.len |
| 337 cdef c_core.MojoHandle* input_handles = NULL |
| 338 cdef uint32_t input_handles_length = 0 |
| 339 cdef _ScopedMemory handles_alloc = None |
| 340 if handles: |
| 341 input_handles_length = len(handles) |
| 342 handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) * |
| 343 input_handles_length) |
| 344 input_handles = <c_core.MojoHandle*>handles_alloc.memory |
| 345 for i in xrange(input_handles_length): |
| 346 input_handles[i] = (<Handle?>handles[i])._mojo_handle |
| 347 cdef c_core.MojoResult res = c_core.MojoWriteMessage(self._mojo_handle, |
| 348 buffer_as_buffer.buf, |
| 349 input_buffer_length, |
| 350 input_handles, |
| 351 input_handles_length, |
| 352 flags) |
| 353 if res == c_core.MOJO_RESULT_OK and handles: |
| 354 # Handles have been transferred. Let's invalidate those. |
| 355 for handle in handles: |
| 356 handle._invalidate() |
| 357 return res |
| 358 |
| 359 def read_message(self, |
| 360 buffer=None, |
| 361 max_number_of_handles=0, |
| 362 flags=READ_MESSAGE_FLAG_NONE): |
| 363 """Reads a message from the message pipe. |
| 364 |
| 365 This method can only be used on a handle obtained from |MessagePipe()|. |
| 366 |
| 367 This method returns a triplet of value (code, data, sizes): |
| 368 - if code is RESULT_OK, sizes will be None, and data will be a pair of |
| 369 (buffer, handles) where buffer is a view of the input buffer with the read |
| 370 data, and handles is a list of received handles. |
| 371 - if code is RESULT_RESOURCE_EXHAUSTED, data will be None and sizes will be |
| 372 a pair of (buffer_size, handles_size) where buffer_size is the size of the |
| 373 next message data and handles_size is the number of handles in the next |
| 374 message. |
| 375 - if code is any other value, data and sizes will be None. |
| 376 |
| 377 See mojo/public/c/system/message_pipe.h |
| 378 """ |
| 379 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer, PyBUF_CONTIG) |
| 380 cdef uint32_t input_buffer_length = buffer_as_buffer.len |
| 381 cdef c_core.MojoHandle* input_handles = NULL |
| 382 cdef uint32_t input_handles_length = 0 |
| 383 cdef _ScopedMemory handles_alloc = None |
| 384 if max_number_of_handles > 0: |
| 385 input_handles_length = max_number_of_handles |
| 386 handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) * |
| 387 input_handles_length) |
| 388 input_handles = <c_core.MojoHandle*>handles_alloc.memory |
| 389 cdef res = c_core.MojoReadMessage(self._mojo_handle, |
| 390 buffer_as_buffer.buf, |
| 391 &input_buffer_length, |
| 392 input_handles, |
| 393 &input_handles_length, |
| 394 flags) |
| 395 if res == c_core.MOJO_RESULT_RESOURCE_EXHAUSTED: |
| 396 return (res, None, (input_buffer_length, input_handles_length)) |
| 397 if res == c_core.MOJO_RESULT_OK: |
| 398 returned_handles = [Handle(input_handles[i]) |
| 399 for i in xrange(input_handles_length)] |
| 400 return (res, |
| 401 (_slice_buffer(buffer, input_buffer_length), returned_handles), |
| 402 None) |
| 403 return (res, None, None) |
| 404 |
| 405 def write_data(self, buffer=None, flags=WRITE_DATA_FLAG_NONE): |
| 406 """ |
| 407 Writes the given data to the data pipe producer. |
| 408 |
| 409 This method can only be used on a producer handle obtained from |
| 410 |DataPipe()|. |
| 411 |
| 412 This method returns a tuple (code, num_bytes). |
| 413 - If code is RESULT_OK, num_bytes is the number of written bytes. |
| 414 - Otherwise, num_bytes is None. |
| 415 |
| 416 See mojo/public/c/system/data_pipe.h |
| 417 """ |
| 418 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) |
| 419 cdef uint32_t input_buffer_length = buffer_as_buffer.len |
| 420 cdef c_core.MojoResult res = c_core.MojoWriteData(self._mojo_handle, |
| 421 buffer_as_buffer.buf, |
| 422 &input_buffer_length, |
| 423 flags) |
| 424 if res == c_core.MOJO_RESULT_OK: |
| 425 return (res, input_buffer_length) |
| 426 return (res, None) |
| 427 |
| 428 def begin_write_data(self, |
| 429 min_size=None, |
| 430 flags=WRITE_DATA_FLAG_NONE): |
| 431 """ |
| 432 Begins a two-phase write to the data pipe producer. |
| 433 |
| 434 This method can only be used on a producer handle obtained from |
| 435 |DataPipe()|. |
| 436 |
| 437 This method returns a tuple (code, two_phase_buffer). |
| 438 - If code is RESULT_OK, two_phase_buffer is a writable |
| 439 DataPipeTwoPhaseBuffer |
| 440 - Otherwise, two_phase_buffer is None. |
| 441 |
| 442 See mojo/public/c/system/data_pipe.h |
| 443 """ |
| 444 cdef void* out_buffer |
| 445 cdef uint32_t out_size = 0 |
| 446 if min_size: |
| 447 flags |= c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE |
| 448 out_size = min_size |
| 449 cdef c_core.MojoResult res = c_core.MojoBeginWriteData(self._mojo_handle, |
| 450 &out_buffer, |
| 451 &out_size, |
| 452 flags) |
| 453 if res != c_core.MOJO_RESULT_OK: |
| 454 return (res, None) |
| 455 cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) |
| 456 view_buffer.wrap(out_buffer, out_size, read_only=False) |
| 457 return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), False)) |
| 458 |
| 459 def read_data(self, buffer=None, flags=READ_DATA_FLAG_NONE): |
| 460 """Reads data from the data pipe consumer. |
| 461 |
| 462 This method can only be used on a consumer handle obtained from |
| 463 |DataPipe()|. |
| 464 |
| 465 This method returns a tuple (code, buffer) |
| 466 - if code is RESULT_OK, buffer will be a view of the input buffer with the |
| 467 read data. |
| 468 - otherwise, buffer will be None. |
| 469 |
| 470 See mojo/public/c/system/data_pipe.h |
| 471 """ |
| 472 cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) |
| 473 cdef uint32_t input_buffer_length = buffer_as_buffer.len |
| 474 cdef c_core.MojoResult res = c_core.MojoReadData(self._mojo_handle, |
| 475 buffer_as_buffer.buf, |
| 476 &input_buffer_length, |
| 477 flags) |
| 478 if res == c_core.MOJO_RESULT_OK: |
| 479 return (res, _slice_buffer(buffer, input_buffer_length)) |
| 480 return (res, None) |
| 481 |
| 482 def query_data(self, flags=READ_DATA_FLAG_NONE): |
| 483 """Queries the amount of data available on the data pipe consumer. |
| 484 |
| 485 This method can only be used on a consumer handle obtained from |
| 486 |DataPipe()|. |
| 487 |
| 488 This method returns a tuple (code, num_bytes) |
| 489 - if code is RESULT_OK, num_bytes will be the number of bytes available on |
| 490 the data pipe consumer. |
| 491 - otherwise, num_bytes will be None. |
| 492 |
| 493 See mojo/public/c/system/data_pipe.h |
| 494 """ |
| 495 cdef uint32_t num_bytes = 0 |
| 496 cdef c_core.MojoResult res = c_core.MojoReadData( |
| 497 self._mojo_handle, |
| 498 NULL, |
| 499 &num_bytes, |
| 500 flags|c_core.MOJO_READ_DATA_FLAG_QUERY) |
| 501 return (res, num_bytes) |
| 502 |
| 503 def begin_read_data(self, min_size=None, flags=READ_DATA_FLAG_NONE): |
| 504 """ |
| 505 Begins a two-phase read to the data pipe consumer. |
| 506 |
| 507 This method can only be used on a consumer handle obtained from |
| 508 |DataPipe()|. |
| 509 |
| 510 This method returns a tuple (code, two_phase_buffer). |
| 511 - If code is RESULT_OK, two_phase_buffer is a readable |
| 512 DataPipeTwoPhaseBuffer |
| 513 - Otherwise, two_phase_buffer is None. |
| 514 |
| 515 See mojo/public/c/system/data_pipe.h |
| 516 """ |
| 517 cdef const void* out_buffer |
| 518 cdef uint32_t out_size = 0 |
| 519 if min_size: |
| 520 flags |= c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE |
| 521 out_size = min_size |
| 522 cdef c_core.MojoResult res = c_core.MojoBeginReadData(self._mojo_handle, |
| 523 &out_buffer, |
| 524 &out_size, |
| 525 flags) |
| 526 if res != c_core.MOJO_RESULT_OK: |
| 527 return (res, None) |
| 528 cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) |
| 529 view_buffer.wrap(out_buffer, out_size, read_only=True) |
| 530 return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), True)) |
| 531 |
| 532 def duplicate(self, options=None): |
| 533 """Duplicate the shared buffer handle. |
| 534 |
| 535 This method can only be used on a handle obtained from |
| 536 |create_shared_buffer()| or |duplicate()|. |
| 537 |
| 538 See mojo/public/c/system/buffer.h |
| 539 """ |
| 540 cdef c_core.MojoDuplicateBufferHandleOptions coptions |
| 541 cdef c_core.MojoDuplicateBufferHandleOptions* coptions_ptr = NULL |
| 542 cdef c_core.MojoHandle cnew_handle = c_core.MOJO_HANDLE_INVALID |
| 543 if options: |
| 544 coptions.struct_size = sizeof(c_core.MojoDuplicateBufferHandleOptions) |
| 545 coptions.flags = options.flags |
| 546 coptions_ptr = &coptions |
| 547 cdef c_core.MojoResult result = c_core.MojoDuplicateBufferHandle( |
| 548 self._mojo_handle, coptions_ptr, &cnew_handle) |
| 549 new_handle = Handle(cnew_handle) |
| 550 if result != c_core.MOJO_RESULT_OK: |
| 551 raise MojoException(result) |
| 552 return new_handle |
| 553 |
| 554 def map(self, offset, num_bytes, flags=MAP_BUFFER_FLAG_NONE): |
| 555 """Maps the part (at offset |offset| of length |num_bytes|) of the buffer. |
| 556 |
| 557 This method can only be used on a handle obtained from |
| 558 |create_shared_buffer()| or |duplicate()|. |
| 559 |
| 560 This method returns a tuple (code, mapped_buffer). |
| 561 - If code is RESULT_OK, mapped_buffer is a readable/writable |
| 562 MappedBuffer |
| 563 - Otherwise, mapped_buffer is None. |
| 564 |
| 565 See mojo/public/c/system/buffer.h |
| 566 """ |
| 567 cdef void* buffer |
| 568 res = c_core.MojoMapBuffer(self._mojo_handle, |
| 569 offset, |
| 570 num_bytes, |
| 571 &buffer, |
| 572 flags) |
| 573 if res != c_core.MOJO_RESULT_OK: |
| 574 return (res, None) |
| 575 cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) |
| 576 view_buffer.wrap(buffer, num_bytes, read_only=False) |
| 577 return (res, MappedBuffer(self, |
| 578 memoryview(view_buffer), |
| 579 lambda: c_core.MojoUnmapBuffer(buffer))) |
| 580 |
| 581 class CreateMessagePipeOptions(object): |
| 582 """Options for creating a message pipe. |
| 583 |
| 584 See mojo/public/c/system/message_pipe.h |
| 585 """ |
| 586 FLAG_NONE = c_core.MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE |
| 587 |
| 588 def __init__(self): |
| 589 self.flags = CreateMessagePipeOptions.FLAG_NONE |
| 590 |
| 591 class MessagePipe(object): |
| 592 """Creates a message pipe. |
| 593 |
| 594 The two ends of the message pipe are accessible with the members handle0 and |
| 595 handle1. |
| 596 |
| 597 See mojo/public/c/system/message_pipe.h |
| 598 """ |
| 599 def __init__(self, options=None): |
| 600 cdef c_core.MojoCreateMessagePipeOptions coptions |
| 601 cdef c_core.MojoCreateMessagePipeOptions* coptions_ptr = NULL |
| 602 cdef c_core.MojoHandle chandle0 = c_core.MOJO_HANDLE_INVALID |
| 603 cdef c_core.MojoHandle chandle1 = c_core.MOJO_HANDLE_INVALID |
| 604 if options: |
| 605 coptions.struct_size = sizeof(c_core.MojoCreateMessagePipeOptions) |
| 606 coptions.flags = options.flags |
| 607 coptions_ptr = &coptions |
| 608 cdef c_core.MojoResult result = c_core.MojoCreateMessagePipe(coptions_ptr, |
| 609 &chandle0, |
| 610 &chandle1) |
| 611 self.handle0 = Handle(chandle0) |
| 612 self.handle1 = Handle(chandle1) |
| 613 if result != c_core.MOJO_RESULT_OK: |
| 614 raise c_core.MojoException(result) |
| 615 |
| 616 |
| 617 class CreateDataPipeOptions(object): |
| 618 """Options for creating a data pipe. |
| 619 |
| 620 See mojo/public/c/system/data_pipe.h |
| 621 """ |
| 622 FLAG_NONE = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE |
| 623 FLAG_MAY_DISCARD = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD |
| 624 |
| 625 def __init__(self): |
| 626 self.flags = CreateDataPipeOptions.FLAG_NONE |
| 627 self.element_num_bytes = 1 |
| 628 self.capacity_num_bytes = 0 |
| 629 |
| 630 class DataPipe(object): |
| 631 """Creates a data pipe. |
| 632 |
| 633 The producer end of the data pipe is accessible with the member |
| 634 producer_handle and the consumer end of the data pipe is accessible with the |
| 635 member cconsumer_handle. |
| 636 |
| 637 See mojo/public/c/system/data_pipe.h |
| 638 """ |
| 639 def __init__(self, options=None): |
| 640 cdef c_core.MojoCreateDataPipeOptions coptions |
| 641 cdef c_core.MojoCreateDataPipeOptions* coptions_ptr = NULL |
| 642 cdef c_core.MojoHandle cproducer_handle = c_core.MOJO_HANDLE_INVALID |
| 643 cdef c_core.MojoHandle cconsumer_handle = c_core.MOJO_HANDLE_INVALID |
| 644 if options: |
| 645 coptions.struct_size = sizeof(c_core.MojoCreateDataPipeOptions) |
| 646 coptions.flags = options.flags |
| 647 coptions.element_num_bytes = options.element_num_bytes |
| 648 coptions.capacity_num_bytes = options.capacity_num_bytes |
| 649 coptions_ptr = &coptions |
| 650 cdef c_core.MojoResult result = c_core.MojoCreateDataPipe(coptions_ptr, |
| 651 &cproducer_handle, |
| 652 &cconsumer_handle) |
| 653 self.producer_handle = Handle(cproducer_handle) |
| 654 self.consumer_handle = Handle(cconsumer_handle) |
| 655 if result != c_core.MOJO_RESULT_OK: |
| 656 raise MojoException(result) |
| 657 |
| 658 class CreateSharedBufferOptions(object): |
| 659 """Options for creating a shared buffer. |
| 660 |
| 661 See mojo/public/c/system/buffer.h |
| 662 """ |
| 663 FLAG_NONE = c_core.MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE |
| 664 |
| 665 def __init__(self): |
| 666 self.flags = CreateSharedBufferOptions.FLAG_NONE |
| 667 |
| 668 def create_shared_buffer(num_bytes, options=None): |
| 669 """Creates a buffer of size |num_bytes| bytes that can be shared. |
| 670 |
| 671 See mojo/public/c/system/buffer.h |
| 672 """ |
| 673 cdef c_core.MojoCreateSharedBufferOptions coptions |
| 674 cdef c_core.MojoCreateSharedBufferOptions* coptions_ptr = NULL |
| 675 cdef c_core.MojoHandle chandle = c_core.MOJO_HANDLE_INVALID |
| 676 if options: |
| 677 coptions.struct_size = sizeof(c_core.MojoCreateSharedBufferOptions) |
| 678 coptions.flags = options.flags |
| 679 coptions_ptr = &coptions |
| 680 cdef c_core.MojoResult result = c_core.MojoCreateSharedBuffer(coptions_ptr, |
| 681 num_bytes, |
| 682 &chandle) |
| 683 handle = Handle(chandle) |
| 684 if result != c_core.MOJO_RESULT_OK: |
| 685 raise MojoException(result) |
| 686 return handle |
| 687 |
| 688 class DuplicateSharedBufferOptions(object): |
| 689 """Options for duplicating a shared buffer. |
| 690 |
| 691 See mojo/public/c/system/buffer.h |
| 692 """ |
| 693 FLAG_NONE = c_core.MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE |
| 694 |
| 695 def __init__(self): |
| 696 self.flags = DuplicateSharedBufferOptions.FLAG_NONE |
OLD | NEW |