devela::_dep::sysinfo

Struct System

pub struct System { /* private fields */ }
Available on crate feature dep_sysinfo only.
Expand description

Structs containing system’s information such as processes, memory and CPU.

use sysinfo::System;

if sysinfo::IS_SUPPORTED_SYSTEM {
    println!("System: {:?}", System::new_all());
} else {
    println!("This OS isn't supported (yet?).");
}

Implementations§

§

impl System

pub fn new() -> System

Creates a new System instance with nothing loaded.

Use one of the refresh methods (like refresh_all) to update its internal information.

use sysinfo::System;

let s = System::new();

pub fn new_all() -> System

Creates a new System instance with everything loaded.

It is an equivalent of System::new_with_specifics(RefreshKind::everything()).

use sysinfo::System;

let s = System::new_all();

pub fn new_with_specifics(refreshes: RefreshKind) -> System

Creates a new System instance and refresh the data corresponding to the given RefreshKind.

use sysinfo::{ProcessRefreshKind, RefreshKind, System};

// We want to only refresh processes.
let mut system = System::new_with_specifics(
     RefreshKind::nothing().with_processes(ProcessRefreshKind::everything()),
);

assert!(!system.processes().is_empty());

pub fn refresh_specifics(&mut self, refreshes: RefreshKind)

Refreshes according to the given RefreshKind. It calls the corresponding “refresh_” methods.

use sysinfo::{ProcessRefreshKind, RefreshKind, System};

let mut s = System::new_all();

// Let's just update processes:
s.refresh_specifics(
    RefreshKind::nothing().with_processes(ProcessRefreshKind::everything()),
);

pub fn refresh_all(&mut self)

Refreshes all system and processes information.

It is the same as calling system.refresh_specifics(RefreshKind::everything()).

Don’t forget to take a look at ProcessRefreshKind::everything method to see what it will update for processes more in details.

use sysinfo::System;

let mut s = System::new();
s.refresh_all();

pub fn refresh_memory(&mut self)

Refreshes RAM and SWAP usage.

It is the same as calling system.refresh_memory_specifics(MemoryRefreshKind::everything()).

If you don’t want to refresh both, take a look at System::refresh_memory_specifics.

use sysinfo::System;

let mut s = System::new();
s.refresh_memory();

pub fn refresh_memory_specifics(&mut self, refresh_kind: MemoryRefreshKind)

Refreshes system memory specific information.

use sysinfo::{MemoryRefreshKind, System};

let mut s = System::new();
s.refresh_memory_specifics(MemoryRefreshKind::nothing().with_ram());

pub fn refresh_cpu_usage(&mut self)

Refreshes CPUs usage.

⚠️ Please note that the result will very likely be inaccurate at the first call. You need to call this method at least twice (with a bit of time between each call, like 200 ms, take a look at MINIMUM_CPU_UPDATE_INTERVAL for more information) to get accurate value as it uses previous results to compute the next value.

Calling this method is the same as calling system.refresh_cpu_specifics(CpuRefreshKind::nothing().with_cpu_usage()).

use sysinfo::System;

let mut s = System::new_all();
// Wait a bit because CPU usage is based on diff.
std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
// Refresh CPUs again.
s.refresh_cpu_usage();

pub fn refresh_cpu_frequency(&mut self)

Refreshes CPUs frequency information.

Calling this method is the same as calling system.refresh_cpu_specifics(CpuRefreshKind::nothing().with_frequency()).

use sysinfo::System;

let mut s = System::new_all();
s.refresh_cpu_frequency();

pub fn refresh_cpu_list(&mut self, refresh_kind: CpuRefreshKind)

Refreshes the list of CPU.

Normally, this should almost never be needed as it’s pretty rare for a computer to add a CPU while running, but it’s possible on some computers which shutdown CPU if the load is low enough.

The refresh_kind argument tells what information you want to be retrieved for each CPU.

use sysinfo::{CpuRefreshKind, System};

let mut s = System::new_all();
// We already have the list of CPU filled, but we want to recompute it
// in case new CPUs were added.
s.refresh_cpu_list(CpuRefreshKind::everything());

pub fn refresh_cpu_all(&mut self)

Refreshes all information related to CPUs information.

If you only want the CPU usage, use System::refresh_cpu_usage instead.

⚠️ Please note that the result will be inaccurate at the first call. You need to call this method at least twice (with a bit of time between each call, like 200 ms, take a look at MINIMUM_CPU_UPDATE_INTERVAL for more information) to get accurate value as it uses previous results to compute the next value.

Calling this method is the same as calling system.refresh_cpu_specifics(CpuRefreshKind::everything()).

use sysinfo::System;

let mut s = System::new_all();
s.refresh_cpu_all();

pub fn refresh_cpu_specifics(&mut self, refresh_kind: CpuRefreshKind)

Refreshes CPUs specific information.

use sysinfo::{System, CpuRefreshKind};

let mut s = System::new_all();
s.refresh_cpu_specifics(CpuRefreshKind::everything());

pub fn refresh_processes( &mut self, processes_to_update: ProcessesToUpdate<'_>, remove_dead_processes: bool, ) -> usize

Gets all processes and updates their information.

It does the same as:

system.refresh_processes_specifics(
    ProcessesToUpdate::All,
    true,
    ProcessRefreshKind::nothing()
        .with_memory()
        .with_cpu()
        .with_disk_usage()
        .with_exe(UpdateKind::OnlyIfNotSet),
);

⚠️ remove_dead_processes works as follows: if an updated process is dead, then it is removed. So if you refresh pids 1, 2 and 3. If 2 and 7 are dead, only 2 will be removed since 7 is not part of the update.

⚠️ On Linux, sysinfo keeps the stat files open by default. You can change this behaviour by using set_open_files_limit.

Example:

use sysinfo::{ProcessesToUpdate, System};

let mut s = System::new_all();
s.refresh_processes(ProcessesToUpdate::All, true);

pub fn refresh_processes_specifics( &mut self, processes_to_update: ProcessesToUpdate<'_>, remove_dead_processes: bool, refresh_kind: ProcessRefreshKind, ) -> usize

Gets all processes and updates the specified information.

Returns the number of updated processes.

⚠️ remove_dead_processes works as follows: if an updated process is dead, then it is removed. So if you refresh pids 1, 2 and 3. If 2 and 7 are dead, only 2 will be removed since 7 is not part of the update.

⚠️ On Linux, sysinfo keeps the stat files open by default. You can change this behaviour by using set_open_files_limit.

use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System};

let mut s = System::new_all();
s.refresh_processes_specifics(
    ProcessesToUpdate::All,
    true,
    ProcessRefreshKind::everything(),
);

pub fn processes(&self) -> &HashMap<Pid, Process>

Returns the process list.

use sysinfo::System;

let s = System::new_all();
for (pid, process) in s.processes() {
    println!("{} {:?}", pid, process.name());
}

pub fn process(&self, pid: Pid) -> Option<&Process>

Returns the process corresponding to the given pid or None if no such process exists.

use sysinfo::{Pid, System};

let s = System::new_all();
if let Some(process) = s.process(Pid::from(1337)) {
    println!("{:?}", process.name());
}

pub fn processes_by_name<'a, 'b>( &'a self, name: &'b OsStr, ) -> impl Iterator<Item = &'a Process> + 'b
where 'a: 'b,

Returns an iterator of process containing the given name.

If you want only the processes with exactly the given name, take a look at System::processes_by_exact_name.

⚠️ Important ⚠️

On Linux, there are two things to know about processes’ name:

  1. It is limited to 15 characters.
  2. It is not always the exe name.
use sysinfo::System;

let s = System::new_all();
for process in s.processes_by_name("htop".as_ref()) {
    println!("{} {:?}", process.pid(), process.name());
}

pub fn processes_by_exact_name<'a, 'b>( &'a self, name: &'b OsStr, ) -> impl Iterator<Item = &'a Process> + 'b
where 'a: 'b,

Returns an iterator of processes with exactly the given name.

If you instead want the processes containing name, take a look at System::processes_by_name.

⚠️ Important ⚠️

On Linux, there are two things to know about processes’ name:

  1. It is limited to 15 characters.
  2. It is not always the exe name.
use sysinfo::System;

let s = System::new_all();
for process in s.processes_by_exact_name("htop".as_ref()) {
    println!("{} {:?}", process.pid(), process.name());
}

pub fn global_cpu_usage(&self) -> f32

Returns “global” CPUs usage (aka the addition of all the CPUs).

To have up-to-date information, you need to call System::refresh_cpu_specifics or System::refresh_specifics with cpu enabled.

use sysinfo::{CpuRefreshKind, RefreshKind, System};

let mut s = System::new_with_specifics(
    RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
);
// Wait a bit because CPU usage is based on diff.
std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
// Refresh CPUs again to get actual value.
s.refresh_cpu_usage();
println!("{}%", s.global_cpu_usage());

pub fn cpus(&self) -> &[Cpu]

Returns the list of the CPUs.

By default, the list of CPUs is empty until you call System::refresh_cpu_specifics or System::refresh_specifics with cpu enabled.

use sysinfo::{CpuRefreshKind, RefreshKind, System};

let mut s = System::new_with_specifics(
    RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
);
// Wait a bit because CPU usage is based on diff.
std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
// Refresh CPUs again to get actual value.
s.refresh_cpu_usage();
for cpu in s.cpus() {
    println!("{}%", cpu.cpu_usage());
}

pub fn physical_core_count(&self) -> Option<usize>

Returns the number of physical cores on the CPU or None if it couldn’t get it.

In case there are multiple CPUs, it will combine the physical core count of all the CPUs.

Important: this information is computed every time this function is called.

use sysinfo::System;

let s = System::new();
println!("{:?}", s.physical_core_count());

pub fn total_memory(&self) -> u64

Returns the RAM size in bytes.

use sysinfo::System;

let s = System::new_all();
println!("{} bytes", s.total_memory());

On Linux, if you want to see this information with the limit of your cgroup, take a look at cgroup_limits.

pub fn free_memory(&self) -> u64

Returns the amount of free RAM in bytes.

Generally, “free” memory refers to unallocated memory whereas “available” memory refers to memory that is available for (re)use.

Side note: Windows doesn’t report “free” memory so this method returns the same value as available_memory.

use sysinfo::System;

let s = System::new_all();
println!("{} bytes", s.free_memory());

pub fn available_memory(&self) -> u64

Returns the amount of available RAM in bytes.

Generally, “free” memory refers to unallocated memory whereas “available” memory refers to memory that is available for (re)use.

⚠️ Windows and FreeBSD don’t report “available” memory so System::free_memory returns the same value as this method.

use sysinfo::System;

let s = System::new_all();
println!("{} bytes", s.available_memory());

pub fn used_memory(&self) -> u64

Returns the amount of used RAM in bytes.

use sysinfo::System;

let s = System::new_all();
println!("{} bytes", s.used_memory());

pub fn total_swap(&self) -> u64

Returns the SWAP size in bytes.

use sysinfo::System;

let s = System::new_all();
println!("{} bytes", s.total_swap());

pub fn free_swap(&self) -> u64

Returns the amount of free SWAP in bytes.

use sysinfo::System;

let s = System::new_all();
println!("{} bytes", s.free_swap());

pub fn used_swap(&self) -> u64

Returns the amount of used SWAP in bytes.

use sysinfo::System;

let s = System::new_all();
println!("{} bytes", s.used_swap());

pub fn cgroup_limits(&self) -> Option<CGroupLimits>

Retrieves the limits for the current cgroup (if any), otherwise it returns None.

This information is computed every time the method is called.

⚠️ You need to have run refresh_memory at least once before calling this method.

⚠️ This method is only implemented for Linux. It always returns None for all other systems.

use sysinfo::System;

let s = System::new_all();
println!("limits: {:?}", s.cgroup_limits());

pub fn uptime() -> u64

Returns system uptime (in seconds).

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("System running since {} seconds", System::uptime());

pub fn boot_time() -> u64

Returns the time (in seconds) when the system booted since UNIX epoch.

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("System booted at {} seconds", System::boot_time());

pub fn load_average() -> LoadAvg

Returns the system load average value.

Important: this information is computed every time this function is called.

⚠️ This is currently not working on Windows.

use sysinfo::System;

let load_avg = System::load_average();
println!(
    "one minute: {}%, five minutes: {}%, fifteen minutes: {}%",
    load_avg.one,
    load_avg.five,
    load_avg.fifteen,
);

pub fn name() -> Option<String>

Returns the system name.

example platformvalue of System::name()
linux laptop“Ubuntu”
android phone“Pixel 9 Pro”
apple laptop“Darwin”
windows server“Windows”

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("OS: {:?}", System::name());

pub fn kernel_version() -> Option<String>

Returns the system’s kernel version.

example platformvalue of System::kernel_version()
linux laptop“6.8.0-48-generic”
android phone“6.1.84-android14-11”
apple laptop“24.1.0”
windows server“20348”

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("kernel version: {:?}", System::kernel_version());

pub fn os_version() -> Option<String>

Returns the system version (e.g. for macOS this will return 15.1 rather than the kernel version).

example platformvalue of System::os_version()
linux laptop“24.04”
android phone“15”
apple laptop“15.1.1”
windows server“10 (20348)”

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("OS version: {:?}", System::os_version());

pub fn long_os_version() -> Option<String>

Returns the system long os version.

example platformvalue of System::long_os_version()
linux laptop“Linux (Ubuntu 24.04)”
android phone“Android 15 on Pixel 9 Pro”
apple laptop“macOS 15.1.1 Sequoia”
windows server“Windows Server 2022 Datacenter”

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("Long OS Version: {:?}", System::long_os_version());

pub fn distribution_id() -> String

Returns the distribution id as defined by os-release, or std::env::consts::OS.

See also

example platformvalue of System::distribution_id()
linux laptop“ubuntu”
android phone“android”
apple laptop“macos”
windows server“windows”

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("Distribution ID: {:?}", System::distribution_id());

pub fn host_name() -> Option<String>

Returns the system hostname based off DNS.

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("Hostname: {:?}", System::host_name());

pub fn cpu_arch() -> String

Returns the CPU architecture (eg. x86, amd64, aarch64, …).

Important: this information is computed every time this function is called.

use sysinfo::System;

println!("CPU Architecture: {:?}", System::cpu_arch());

Trait Implementations§

§

impl Debug for System

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Default for System

§

fn default() -> System

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for System

§

impl RefUnwindSafe for System

§

impl Send for System

§

impl Sync for System

§

impl Unpin for System

§

impl UnwindSafe for System

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> ArchivePointee for T

§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByteSized for T

Source§

const BYTE_ALIGN: usize = _

The alignment of this type in bytes.
Source§

const BYTE_SIZE: usize = _

The size of this type in bytes.
Source§

fn byte_align(&self) -> usize

Returns the alignment of this type in bytes.
Source§

fn byte_size(&self) -> usize

Returns the size of this type in bytes. Read more
Source§

fn ptr_size_ratio(&self) -> [usize; 2]

Returns the size ratio between Ptr::BYTES and BYTE_SIZE. Read more
Source§

impl<T, R> Chain<R> for T
where T: ?Sized,

Source§

fn chain<F>(self, f: F) -> R
where F: FnOnce(Self) -> R, Self: Sized,

Chain a function which takes the parameter by value.
Source§

fn chain_ref<F>(&self, f: F) -> R
where F: FnOnce(&Self) -> R,

Chain a function which takes the parameter by shared reference.
Source§

fn chain_mut<F>(&mut self, f: F) -> R
where F: FnOnce(&mut Self) -> R,

Chain a function which takes the parameter by exclusive reference.
Source§

impl<T> ExtAny for T
where T: Any + ?Sized,

Source§

fn type_id() -> TypeId

Returns the TypeId of Self. Read more
Source§

fn type_of(&self) -> TypeId

Returns the TypeId of self. Read more
Source§

fn type_name(&self) -> &'static str

Returns the type name of self. Read more
Source§

fn type_is<T: 'static>(&self) -> bool

Returns true if Self is of type T. Read more
Source§

fn as_any_ref(&self) -> &dyn Any
where Self: Sized,

Upcasts &self as &dyn Any. Read more
Source§

fn as_any_mut(&mut self) -> &mut dyn Any
where Self: Sized,

Upcasts &mut self as &mut dyn Any. Read more
Source§

fn as_any_box(self: Box<Self>) -> Box<dyn Any>
where Self: Sized,

Upcasts Box<self> as Box<dyn Any>. Read more
Source§

fn downcast_ref<T: 'static>(&self) -> Option<&T>

Available on crate feature unsafe_layout only.
Returns some shared reference to the inner value if it is of type T. Read more
Source§

fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T>

Available on crate feature unsafe_layout only.
Returns some exclusive reference to the inner value if it is of type T. Read more
Source§

impl<T> ExtMem for T
where T: ?Sized,

Source§

const NEEDS_DROP: bool = _

Know whether dropping values of this type matters, in compile-time.
Source§

fn mem_align_of<T>() -> usize

Returns the minimum alignment of the type in bytes. Read more
Source§

fn mem_align_of_val(&self) -> usize

Returns the alignment of the pointed-to value in bytes. Read more
Source§

fn mem_size_of<T>() -> usize

Returns the size of a type in bytes. Read more
Source§

fn mem_size_of_val(&self) -> usize

Returns the size of the pointed-to value in bytes. Read more
Source§

fn mem_copy(&self) -> Self
where Self: Copy,

Bitwise-copies a value. Read more
Source§

fn mem_needs_drop(&self) -> bool

Returns true if dropping values of this type matters. Read more
Source§

fn mem_drop(self)
where Self: Sized,

Drops self by running its destructor. Read more
Source§

fn mem_forget(self)
where Self: Sized,

Forgets about self without running its destructor. Read more
Source§

fn mem_replace(&mut self, other: Self) -> Self
where Self: Sized,

Replaces self with other, returning the previous value of self. Read more
Source§

fn mem_take(&mut self) -> Self
where Self: Default,

Replaces self with its default value, returning the previous value of self. Read more
Source§

fn mem_swap(&mut self, other: &mut Self)
where Self: Sized,

Swaps the value of self and other without deinitializing either one. Read more
Source§

unsafe fn mem_zeroed<T>() -> T

Available on crate feature unsafe_layout only.
Returns the value of type T represented by the all-zero byte-pattern. Read more
Source§

unsafe fn mem_transmute_copy<Src, Dst>(src: &Src) -> Dst

Available on crate feature unsafe_layout only.
Returns the value of type T represented by the all-zero byte-pattern. Read more
Source§

fn mem_as_bytes(&self) -> &[u8]
where Self: Sync + Unpin,

Available on crate feature unsafe_slice only.
View a Sync + Unpin self as &[u8]. Read more
Source§

fn mem_as_bytes_mut(&mut self) -> &mut [u8]
where Self: Sync + Unpin,

Available on crate feature unsafe_slice only.
View a Sync + Unpin self as &mut [u8]. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

Source§

impl<T> Hook for T

Source§

fn hook_ref<F>(self, f: F) -> Self
where F: FnOnce(&Self),

Applies a function which takes the parameter by shared reference, and then returns the (possibly) modified owned value. Read more
Source§

fn hook_mut<F>(self, f: F) -> Self
where F: FnOnce(&mut Self),

Applies a function which takes the parameter by exclusive reference, and then returns the (possibly) modified owned value. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

§

fn into_sample(self) -> T

§

impl<T> LayoutRaw for T

§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> Pointee for T

§

type Metadata = ()

The metadata type for pointers and references to this type.
§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

§

impl<T> Ungil for T
where T: Send,