Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: mojo/public/rust/src/system/data_pipe.rs

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/public/rust/src/system/core.rs ('k') | mojo/public/rust/src/system/ffi.rs » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 use std::marker;
6 use std::mem;
7 use std::ops;
8 use std::ptr;
9 use std::slice;
10 use std::vec;
11
12 use system::ffi;
13 // This full import is intentional; nearly every type in mojo_types needs to be used.
14 use system::mojo_types::*;
15 use system::handle;
16 use system::handle::{CastHandle, Handle};
17
18 #[repr(u32)]
19 /// Create flags for data pipes
20 pub enum Create {
21 None = 0,
22 }
23
24 #[repr(u32)]
25 /// Write flags for data pipes
26 pub enum Write {
27 None = 0,
28
29 /// Write all the data to the pipe if possible or none at all
30 AllOrNone = 1 << 0,
31 }
32
33 #[repr(u32)]
34 /// Read flags for data pipes
35 pub enum Read {
36 None = 0,
37
38 /// Read all the data from the pipe if possible, or none at all
39 AllOrNone = 1 << 0,
40
41 /// Dequeue the message recieved rather than reading it
42 Discard = 1 << 1,
43
44 /// Get information about the queue on the pipe but do not perform the
45 /// read
46 Query = 1 << 2,
47
48 /// Read data off the pipe's queue but do not dequeue it
49 Peek = 1 << 3,
50 }
51
52 /// Intermediary structure in a two-phase read.
53 /// Reads of the requested buffer must be done directly
54 /// through this data structure which must then be committed.
55 pub struct ReadDataBuffer<'b, 'p, T>
56 where 'p: 'b,
57 T: 'p
58 {
59 buffer: &'b [T],
60
61 /// Contains a reference to parent to end commit
62 /// and prevent it from outliving its parent handle.
63 parent: &'p Consumer<T>,
64 }
65
66 impl<'b, 'p, T> ReadDataBuffer<'b, 'p, T>
67 where 'p: 'b,
68 T: 'p
69 {
70 /// Attempts to commit the read, that is, end the two-phase read
71 /// started by the parent Consumer<T> object. On a successful
72 /// commit, consumes self, otherwise returns self to try again.
73 pub fn commit(self, bytes_read: usize) -> Option<(Self, MojoResult)> {
74 let result = unsafe { self.parent.end_read(bytes_read) };
75 if result == MojoResult::Okay {
76 None
77 } else {
78 Some((self, result))
79 }
80 }
81
82 /// Returns the length of the underlying buffer
83 pub fn len(&self) -> usize {
84 self.buffer.len()
85 }
86 }
87
88 impl<'b, 'p, T> ops::Index<usize> for ReadDataBuffer<'b, 'p, T>
89 where 'p: 'b,
90 T: 'p
91 {
92 type Output = T;
93
94 /// Overloads the indexing ([]) operator for reads.
95 ///
96 /// Part of reimplementing the array interface to be
97 /// able to use the structure naturally.
98 fn index(&self, index: usize) -> &T {
99 &self.buffer[index]
100 }
101 }
102
103 /// Intermediary structure in a two-phase write.
104 /// Writes to the requested buffer must be done directly
105 /// through this data structure which must then be committed.
106 pub struct WriteDataBuffer<'b, 'p, T>
107 where 'p: 'b,
108 T: 'p
109 {
110 buffer: &'b mut [T],
111
112 /// Contains a reference to parent to end commit
113 /// and prevent it from outliving its parent handle.
114 parent: &'p Producer<T>,
115 }
116
117 impl<'b, 'p, T> WriteDataBuffer<'b, 'p, T>
118 where 'p: 'b,
119 T: 'p
120 {
121 /// Attempts to commit the write, that is, end the two-phase
122 /// write started by a Producer. On a successful
123 /// commit, consumes self, otherwise returns self to try again.
124 pub fn commit(self, bytes_written: usize) -> Option<(Self, MojoResult)> {
125 let result = unsafe { self.parent.end_write(bytes_written) };
126 if result == MojoResult::Okay {
127 None
128 } else {
129 Some((self, result))
130 }
131 }
132
133 /// Returns the length of the underlying buffer
134 pub fn len(&self) -> usize {
135 self.buffer.len()
136 }
137 }
138
139 impl<'b, 'p, T> ops::Index<usize> for WriteDataBuffer<'b, 'p, T>
140 where 'p: 'b,
141 T: 'p
142 {
143 type Output = T;
144
145 /// Overloads the indexing ([]) operator for reads.
146 ///
147 /// Part of reimplementing the array interface to be
148 /// able to use the structure naturally.
149 fn index(&self, index: usize) -> &T {
150 &self.buffer[index]
151 }
152 }
153
154 impl<'b, 'p, T> ops::IndexMut<usize> for WriteDataBuffer<'b, 'p, T>
155 where 'p: 'b,
156 T: 'p
157 {
158 /// Overloads the indexing ([]) operator for writes.
159 ///
160 /// Part of reimplementing the array interface to be
161 /// able to use the structure naturally.
162 fn index_mut(&mut self, index: usize) -> &mut T {
163 &mut self.buffer[index]
164 }
165 }
166
167 /// Creates a data pipe, represented as a consumer
168 /// and a producer. Additionally, we associate a type
169 /// T with the data pipe, as data pipes operate in terms
170 /// of elements. In this way we can enforce type safety.
171 ///
172 /// Capacity, as an input, must be given in number of elements.
173 /// Use a capacity of 0 in order to use some system-dependent
174 /// default capacity.
175 pub fn create<T>(flags: CreateFlags,
176 capacity: u32)
177 -> Result<(Consumer<T>, Producer<T>), MojoResult> {
178 let elem_size = mem::size_of::<T>() as u32;
179 let opts = ffi::MojoCreateDataPipeOptions {
180 struct_size: mem::size_of::<ffi::MojoCreateDataPipeOptions>() as u32,
181 flags: flags,
182 element_num_bytes: elem_size,
183 capacity_num_bytes: capacity * elem_size,
184 _align: [],
185 };
186 // TODO(mknyszek): Make sure handles are valid
187 let mut chandle: MojoHandle = 0;
188 let mut phandle: MojoHandle = 0;
189 let raw_opts = &opts as *const ffi::MojoCreateDataPipeOptions;
190 let r = MojoResult::from_code(unsafe {
191 ffi::MojoCreateDataPipe(raw_opts,
192 &mut phandle as *mut MojoHandle,
193 &mut chandle as *mut MojoHandle)
194 });
195 if r != MojoResult::Okay {
196 Err(r)
197 } else {
198 Ok((Consumer::<T> {
199 handle: unsafe { handle::acquire(chandle) },
200 _elem_type: marker::PhantomData,
201 },
202 Producer::<T> {
203 handle: unsafe { handle::acquire(phandle) },
204 _elem_type: marker::PhantomData,
205 }))
206 }
207 }
208
209 /// Creates a data pipe, represented as a consumer
210 /// and a producer, using the default Mojo options.
211 pub fn create_default() -> Result<(Consumer<u8>, Producer<u8>), MojoResult> {
212 create::<u8>(Create::None as u32, 0)
213 }
214
215 /// Represents the consumer half of a data pipe.
216 /// This data structure wraps a handle and acts
217 /// effectively as a typed handle.
218 ///
219 /// The purpose of the _elem_type field is to associate
220 /// a type with the consumer, as a data pipe works
221 /// in elements.
222 pub struct Consumer<T> {
223 handle: handle::UntypedHandle,
224 _elem_type: marker::PhantomData<T>,
225 }
226
227 impl<T> Consumer<T> {
228 /// Perform a read operation on the consumer end of the data pipe. As
229 /// a result, we get an std::vec::Vec filled with whatever was written.
230 pub fn read(&self, flags: ReadFlags) -> Result<vec::Vec<T>, MojoResult> {
231 let mut num_bytes: u32 = 0;
232 let r_prelim = unsafe {
233 ffi::MojoReadData(self.handle.get_native_handle(),
234 ptr::null_mut() as *mut ffi::c_void,
235 &mut num_bytes as *mut u32,
236 1 << 2 as ReadFlags)
237 };
238 if r_prelim != 0 || num_bytes == 0 {
239 return Err(MojoResult::from_code(r_prelim));
240 }
241 let elem_size: u32 = mem::size_of::<T>() as u32;
242 // TODO(mknyszek): make sure elem_size divides into num_bytes
243 let mut buf: vec::Vec<T> = vec::Vec::with_capacity((num_bytes / elem_siz e) as usize);
244 let r = MojoResult::from_code(unsafe {
245 ffi::MojoReadData(self.handle.get_native_handle(),
246 buf.as_mut_ptr() as *const ffi::c_void,
247 &mut num_bytes as *mut u32,
248 flags)
249 });
250 unsafe { buf.set_len((num_bytes / elem_size) as usize) }
251 if r != MojoResult::Okay {
252 Err(r)
253 } else {
254 Ok(buf)
255 }
256 }
257
258 /// Start two-phase read and return a ReadDataBuffer to perform
259 /// read and commit.
260 pub fn begin(&self, flags: ReadFlags) -> Result<ReadDataBuffer<T>, MojoResul t> {
261 let wrapped_result = unsafe { self.begin_read(flags) };
262 match wrapped_result {
263 Ok(arr) => {
264 Ok(ReadDataBuffer::<T> {
265 buffer: arr,
266 parent: self,
267 })
268 }
269 Err(r) => Err(r),
270 }
271 }
272
273 /// A private function that performs the first half of two-phase reading.
274 /// Kept private because it is unsafe to use (the array received may not
275 /// be valid if end_read is performed).
276 unsafe fn begin_read(&self, flags: ReadFlags) -> Result<&[T], MojoResult> {
277 let mut buf_num_bytes: u32 = 0;
278 let mut pbuf: *mut ffi::c_void = mem::uninitialized();
279 let r = MojoResult::from_code(ffi::MojoBeginReadData(self.handle.get_nat ive_handle(),
280 &mut pbuf,
281 &mut buf_num_bytes as *mut u32,
282 flags));
283 if r != MojoResult::Okay {
284 Err(r)
285 } else {
286 let buf_elems = (buf_num_bytes as usize) / mem::size_of::<T>();
287 let buf = slice::from_raw_parts(pbuf as *mut T, buf_elems);
288 Ok(buf)
289 }
290 }
291
292 /// A private function that performs the second half of two-phase reading.
293 /// Kept private because it is unsafe to use (the array received from start_ read
294 /// may not be valid if end_read is performed).
295 ///
296 /// Also assumes loads/stores aren't reordered such that a load/store may be
297 /// optimized to be run AFTER MojoEndReadData(). In general, this is true as long
298 /// as raw pointers are used, but Rust's memory model is still undefined. If you're
299 /// getting a bad/strange runtime error, it might be for this reason.
300 unsafe fn end_read(&self, elems_read: usize) -> MojoResult {
301 let elem_size = mem::size_of::<T>();
302 MojoResult::from_code(ffi::MojoEndReadData(self.handle.get_native_handle (),
303 (elems_read * elem_size) as u 32))
304 }
305 }
306
307 impl<T> CastHandle for Consumer<T> {
308 /// Generates a Consumer from an untyped handle wrapper
309 /// See mojo::system::handle for information on untyped vs. typed
310 unsafe fn from_untyped(handle: handle::UntypedHandle) -> Self {
311 Consumer::<T> {
312 handle: handle,
313 _elem_type: marker::PhantomData,
314 }
315 }
316
317 /// Consumes this object and produces a plain handle wrapper
318 /// See mojo::system::handle for information on untyped vs. typed
319 fn as_untyped(self) -> handle::UntypedHandle {
320 self.handle
321 }
322 }
323
324 impl<T> Handle for Consumer<T> {
325 /// Returns the native handle wrapped by this structure.
326 ///
327 /// See mojo::system::handle for information on handle wrappers
328 fn get_native_handle(&self) -> MojoHandle {
329 self.handle.get_native_handle()
330 }
331 }
332
333 /// Represents the consumer half of a data pipe.
334 /// This data structure wraps a handle and acts
335 /// effectively as a typed handle.
336 ///
337 /// The purpose of the _elem_type field is to associate
338 /// a type with the consumer, as a data pipe works
339 /// in elements.
340 pub struct Producer<T> {
341 handle: handle::UntypedHandle,
342 _elem_type: marker::PhantomData<T>,
343 }
344
345 impl<T> Producer<T> {
346 /// Perform a write operation on the producer end of the data pipe.
347 /// Returns the number of elements actually written.
348 pub fn write(&self, data: &[T], flags: WriteFlags) -> Result<usize, MojoResu lt> {
349 let mut num_bytes = (data.len() * mem::size_of::<T>()) as u32;
350 let r = MojoResult::from_code(unsafe {
351 ffi::MojoWriteData(self.handle.get_native_handle(),
352 data.as_ptr() as *const ffi::c_void,
353 &mut num_bytes as *mut u32,
354 flags)
355 });
356 if r != MojoResult::Okay {
357 Err(r)
358 } else {
359 Ok(num_bytes as usize)
360 }
361 }
362
363 /// Start two-phase write and return a WriteDataBuffer to perform
364 /// write and commit.
365 ///
366 /// Borrows self as mutable so that no other operation may happen on
367 /// the producer until the two-phase write is committed.
368 pub fn begin(&self, flags: WriteFlags) -> Result<WriteDataBuffer<T>, MojoRes ult> {
369 let wrapped_result = unsafe { self.begin_write(flags) };
370 match wrapped_result {
371 Ok(arr) => {
372 Ok(WriteDataBuffer::<T> {
373 buffer: arr,
374 parent: self,
375 })
376 }
377 Err(r) => Err(r),
378 }
379 }
380
381 /// A private function that performs the first half of two-phase writing.
382 /// Kept private because it is unsafe to use (the array received may not
383 /// be valid if end_write is performed).
384 unsafe fn begin_write(&self, flags: WriteFlags) -> Result<&mut [T], MojoResu lt> {
385 let mut buf_num_bytes: u32 = 0;
386 let mut pbuf: *mut ffi::c_void = mem::uninitialized();
387 let r = MojoResult::from_code(ffi::MojoBeginWriteData(self.handle.get_na tive_handle(),
388 &mut pbuf,
389 &mut buf_num_bytes as *mut u32,
390 flags));
391 if r != MojoResult::Okay {
392 Err(r)
393 } else {
394 let buf_elems = (buf_num_bytes as usize) / mem::size_of::<T>();
395 let buf = slice::from_raw_parts_mut(pbuf as *mut T, buf_elems);
396 Ok(buf)
397 }
398 }
399
400 /// A private function that performs the second half of two-phase writing.
401 /// Kept private because it is unsafe to use (the array received from start_ write
402 /// may not be valid if end_write is performed).
403 ///
404 /// Also assumes loads/stores aren't reordered such that a load/store may be
405 /// optimized to be run AFTER MojoEndWriteData(). In general, this is true a s long
406 /// as raw pointers are used, but Rust's memory model is still undefined. If you're
407 /// getting a bad/strange runtime error, it might be for this reason.
408 unsafe fn end_write(&self, elems_written: usize) -> MojoResult {
409 let elem_size = mem::size_of::<T>();
410 MojoResult::from_code(ffi::MojoEndWriteData(self.handle.get_native_handl e(),
411 (elems_written * elem_size) as u32))
412 }
413 }
414
415 impl<T> CastHandle for Producer<T> {
416 /// Generates a Consumer from an untyped handle wrapper
417 /// See mojo::system::handle for information on untyped vs. typed
418 unsafe fn from_untyped(handle: handle::UntypedHandle) -> Self {
419 Producer::<T> {
420 handle: handle,
421 _elem_type: marker::PhantomData,
422 }
423 }
424
425 /// Consumes this object and produces a plain handle wrapper
426 /// See mojo::system::handle for information on untyped vs. typed
427 fn as_untyped(self) -> handle::UntypedHandle {
428 self.handle
429 }
430 }
431
432 impl<T> Handle for Producer<T> {
433 /// Returns the native handle wrapped by this structure.
434 ///
435 /// See mojo::system::handle for information on handle wrappers
436 fn get_native_handle(&self) -> MojoHandle {
437 self.handle.get_native_handle()
438 }
439 }
OLDNEW
« no previous file with comments | « mojo/public/rust/src/system/core.rs ('k') | mojo/public/rust/src/system/ffi.rs » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698