pub struct DeviceHandle<S: ?Sized, I: DeviceHandleSpec = ChannelDeviceHandle> { /* private fields */ }Expand description
Implementations§
Source§impl<S: DeviceService, I: DeviceHandleSpec> DeviceHandle<S, I>
impl<S: DeviceService, I: DeviceHandleSpec> DeviceHandle<S, I>
pub fn insert( device_id: DeviceId, service: S, ) -> Result<Self, ServiceCreationError>
pub fn new(device_id: DeviceId) -> Self
Sourcepub fn close(device_id: DeviceId) -> Result<(), ServiceCloseError>
pub fn close(device_id: DeviceId) -> Result<(), ServiceCloseError>
Stops serving S on device_id now, though handles to it remain, and drops it on its
runner.
Everything queued ahead of the close runs; every call after it is answered an error
(CallError::is_closed) instead of reaching the service, and S is not started on
the device again. Other services on the same runner keep serving. Only for process
exit, before the runtime under S is torn down, when the threads holding handles will
never drop them; close_at_exit is how a runtime asks for it.
§Errors
When called from inside a call on the service’s own runner, which holds the service, or when the runner does not reach the close in time. The service may still be serving.
Sourcepub fn close_at_exit(device_id: DeviceId)
pub fn close_at_exit(device_id: DeviceId)
Closes S on device_id as the process exits, ahead of the exit teardown of the
libraries it calls into.
On Linux with glibc the close runs as the main thread exits, before any exit handler. Elsewhere, and for an exit from another thread, it runs from an exit handler registered by the first call, ahead of the teardown registered before it: a runtime calls this once its library is loaded and the device set up. Once the process is exiting, no service is started on any device.
Source§impl<S: ?Sized + 'static, I: DeviceHandleSpec> DeviceHandle<S, I>
impl<S: ?Sized + 'static, I: DeviceHandleSpec> DeviceHandle<S, I>
pub const fn is_blocking() -> bool
Sourcepub fn seen_as<T: ?Sized>(
self,
cast: fn(&mut dyn Any) -> &mut T,
) -> DeviceHandle<T, I>
pub fn seen_as<T: ?Sized>( self, cast: fn(&mut dyn Any) -> &mut T, ) -> DeviceHandle<T, I>
The same service, seen as T: cast turns the state this handle
already reaches into a T, once per task, on the thread that runs it.
pub fn device_id(&self) -> DeviceId
Sourcepub fn service_id(&self) -> ServiceId
pub fn service_id(&self) -> ServiceId
The service this handle reaches: its device and its concrete type, whatever it is seen as.
pub fn utilities(&self) -> ServerUtilitiesHandle
pub fn submit_blocking<'a, R: Send, T: FnOnce(&mut S) -> R + Send + 'a>( &self, task: T, ) -> Result<R, CallError>
pub fn submit<T: FnOnce(&mut S) + Send + 'static>(&self, task: T)
Sourcepub fn spawn<R: Send + 'static, T: FnOnce(&mut S) -> R + Send + 'static>(
&self,
task: T,
) -> SpawnedCall<R>
pub fn spawn<R: Send + 'static, T: FnOnce(&mut S) -> R + Send + 'static>( &self, task: T, ) -> SpawnedCall<R>
Runs task without waiting for it, so calls to several devices can run at once.
pub fn flush_queue(&self)
pub fn exclusive<R: Send, T: FnOnce() -> R + Send>( &self, task: T, ) -> Result<R, CallError>
Sourcepub fn shutdown(device_id: DeviceId)
pub fn shutdown(device_id: DeviceId)
Stops the background runner threads for device_id, blocking until they
exit. Queued tasks run before the threads stop. Live handles keep their
runner alive, so all handles for the device should be dropped first.
Only meaningful for handle implementations with background threads; a no-op otherwise.
§Scope
This is device-wide, and S is ignored. It shuts down every
DeviceService registered on device_id, across both service stages, not
only S. The type parameter selects the handle implementation to dispatch
through, nothing more.
DeviceId is not unique across runtimes either: type_id is assigned per
runtime, so distinct backends can hand out the same id. Shutting down a
device from one runtime can therefore tear down another runtime’s services
on the colliding id, and block while that runtime’s handles are still live.