blob: 271178386458cdebb862e769900aa8c0174f18d5 [file] [log] [blame]
// Copyright 2016 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.
use std::mem;
use std::ptr;
use system::ffi;
use system::handle;
use system::handle::{CastHandle, Handle};
use system::mojo_types;
use system::mojo_types::MojoResult;
#[repr(u32)]
/// Create flags for wait sets
pub enum Create {
None = 0,
}
#[repr(u32)]
/// Add flags for wait sets
pub enum Add {
None = 0,
}
/// This struct represents a handle to a wait set in the Mojo system.
///
/// The primary purpose of a wait set is to provide an abstraction for
/// efficiently waiting asynchronously (and cooperatively) on a set of
/// handles which are registered with it.
pub struct WaitSet {
handle: handle::UntypedHandle,
}
impl WaitSet {
/// Creates a new WaitSet object in the Mojo system, and returns a wrapper
/// for it. If creation fails, returns the result code.
pub fn new(flags: mojo_types::CreateFlags) -> Result<WaitSet, MojoResult> {
let mut raw_handle: mojo_types::MojoHandle = 0;
let opts = ffi::MojoCreateWaitSetOptions {
struct_size: mem::size_of::<ffi::MojoCreateWaitSetOptions>() as u32,
flags: flags,
_align: [],
};
let raw_opts = &opts as *const ffi::MojoCreateWaitSetOptions;
let r = MojoResult::from_code(unsafe {
ffi::MojoCreateWaitSet(raw_opts, &mut raw_handle as *mut mojo_types::MojoHandle)
});
if r != MojoResult::Okay {
Err(r)
} else {
Ok(WaitSet { handle: unsafe { handle::acquire(raw_handle) } })
}
}
/// Adds a handle to the underlying wait set.
///
/// The handle that is added may go invalid, at which point the result
/// returned from wait_on_set for this handle will be `Cancelled'.
///
/// One can pass in a unique cookie value which is used to identify the
/// handle in the wait result. Currently there are no supported flags,
/// but the argument is kept for future usage.
pub fn add(
&mut self,
handle: &Handle,
signals: mojo_types::HandleSignals,
cookie: u64,
flags: mojo_types::AddFlags,
) -> MojoResult {
let opts = ffi::MojoWaitSetAddOptions {
struct_size: mem::size_of::<ffi::MojoWaitSetAddOptions>() as u32,
flags: flags,
_align: [],
};
let raw_opts = &opts as *const ffi::MojoWaitSetAddOptions;
MojoResult::from_code(unsafe {
ffi::MojoWaitSetAdd(
self.handle.get_native_handle(),
handle.get_native_handle(),
signals,
cookie,
raw_opts,
)
})
}
/// Removes a handle from the underlying wait set by cookie value.
pub fn remove(&mut self, cookie: u64) -> MojoResult {
MojoResult::from_code(unsafe { ffi::MojoWaitSetRemove(self.get_native_handle(), cookie) })
}
/// Waits on this wait set.
///
/// The conditions for the wait to end include:
/// * A handle has its requested signals satisfied.
/// * A handle is determined to never be able to have its requested
/// signals satisfied.
/// * The deadline expires.
/// * This wait set handle becomes invalid (Fatal error in this bindings).
///
/// On a successful wait, we return the maximum number of results that could
/// possibly be returned (similar to the total number of registered handles).
/// Additionally, populates the output vector with the results of each handle
/// that completed waiting.
///
/// On a failed wait, we return the result code.
pub fn wait_on_set(
&self,
deadline: mojo_types::MojoDeadline,
output: &mut Vec<mojo_types::WaitSetResult>,
) -> Result<u32, MojoResult> {
assert!((output.capacity() as u64) <= ((1 as u64) << 32));
let mut num_results = output.capacity() as u32;
let mut max_results: u32 = 0;
let mut output_ptr = output.as_mut_ptr();
if num_results == 0 {
output_ptr = ptr::null_mut();
}
let r = MojoResult::from_code(unsafe {
ffi::MojoWaitSetWait(
self.handle.get_native_handle(),
deadline,
&mut num_results as *mut u32,
output_ptr,
&mut max_results as *mut u32,
)
});
unsafe {
output.set_len(num_results as usize);
}
if r == MojoResult::Okay {
Ok(max_results)
} else {
Err(r)
}
}
}
impl CastHandle for WaitSet {
/// Generates a WaitSet from an untyped handle wrapper
/// See mojo::system::handle for information on untyped vs. typed
unsafe fn from_untyped(handle: handle::UntypedHandle) -> Self {
WaitSet { handle: handle }
}
/// Consumes this object and produces a plain handle wrapper
/// See mojo::system::handle for information on untyped vs. typed
fn as_untyped(self) -> handle::UntypedHandle {
self.handle
}
}
impl Handle for WaitSet {
/// Returns the native handle wrapped by this structure.
///
/// See mojo::system::handle for information on handle wrappers
fn get_native_handle(&self) -> mojo_types::MojoHandle {
self.handle.get_native_handle()
}
}