#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ExecutionPartition {
AudioCallback,
RealtimeCpu,
AsyncWorker,
BlockingWorker,
External,
}
impl ExecutionPartition {
pub fn requires_realtime_safety(self) -> bool {
matches!(self, Self::AudioCallback | Self::RealtimeCpu)
}
pub fn rank(self) -> u8 {
match self {
Self::AudioCallback => 0,
Self::RealtimeCpu => 1,
Self::AsyncWorker => 2,
Self::BlockingWorker => 3,
Self::External => 4,
}
}
pub fn needs_bridge_to(self, other: ExecutionPartition) -> bool {
self != other
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SafetyContract {
RealtimeSafe,
AllocationAllowed,
BlockingAllowed,
NetworkAllowed,
ExternalService,
}
impl SafetyContract {
pub fn is_valid_for(self, partition: ExecutionPartition) -> bool {
match (partition, self) {
(ExecutionPartition::AudioCallback, SafetyContract::RealtimeSafe) => true,
(ExecutionPartition::AudioCallback, _) => false,
(ExecutionPartition::RealtimeCpu, SafetyContract::RealtimeSafe) => true,
(ExecutionPartition::RealtimeCpu, _) => false,
(ExecutionPartition::AsyncWorker, SafetyContract::NetworkAllowed) => true,
(ExecutionPartition::AsyncWorker, SafetyContract::AllocationAllowed) => true,
(ExecutionPartition::AsyncWorker, SafetyContract::ExternalService) => true,
(ExecutionPartition::AsyncWorker, _) => false,
(ExecutionPartition::BlockingWorker, SafetyContract::BlockingAllowed) => true,
(ExecutionPartition::BlockingWorker, SafetyContract::AllocationAllowed) => true,
(ExecutionPartition::BlockingWorker, _) => false,
(ExecutionPartition::External, SafetyContract::ExternalService) => true,
(ExecutionPartition::External, _) => false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn given_audio_callback_partition_when_requires_realtime_safety_then_true() {
assert!(ExecutionPartition::AudioCallback.requires_realtime_safety());
assert!(ExecutionPartition::RealtimeCpu.requires_realtime_safety());
}
#[test]
fn given_non_realtime_partitions_when_requires_realtime_safety_then_false() {
assert!(!ExecutionPartition::AsyncWorker.requires_realtime_safety());
assert!(!ExecutionPartition::BlockingWorker.requires_realtime_safety());
assert!(!ExecutionPartition::External.requires_realtime_safety());
}
#[test]
fn given_partitions_when_ranked_then_audio_callback_is_lowest() {
assert_eq!(ExecutionPartition::AudioCallback.rank(), 0);
assert!(ExecutionPartition::AudioCallback.rank() < ExecutionPartition::RealtimeCpu.rank());
assert!(ExecutionPartition::RealtimeCpu.rank() < ExecutionPartition::AsyncWorker.rank());
assert!(ExecutionPartition::AsyncWorker.rank() < ExecutionPartition::BlockingWorker.rank());
assert!(ExecutionPartition::BlockingWorker.rank() < ExecutionPartition::External.rank());
}
#[test]
fn given_same_partition_when_needs_bridge_then_false() {
assert!(!ExecutionPartition::RealtimeCpu.needs_bridge_to(ExecutionPartition::RealtimeCpu));
assert!(!ExecutionPartition::AsyncWorker.needs_bridge_to(ExecutionPartition::AsyncWorker));
}
#[test]
fn given_different_partitions_when_needs_bridge_then_true() {
assert!(ExecutionPartition::RealtimeCpu.needs_bridge_to(ExecutionPartition::AsyncWorker));
assert!(ExecutionPartition::AudioCallback.needs_bridge_to(ExecutionPartition::External));
}
#[test]
fn given_realtime_safe_contract_when_valid_for_audio_callback_then_true() {
assert!(SafetyContract::RealtimeSafe.is_valid_for(ExecutionPartition::AudioCallback));
assert!(SafetyContract::RealtimeSafe.is_valid_for(ExecutionPartition::RealtimeCpu));
}
#[test]
fn given_allocation_allowed_contract_when_valid_for_audio_callback_then_false() {
assert!(!SafetyContract::AllocationAllowed.is_valid_for(ExecutionPartition::AudioCallback));
assert!(!SafetyContract::AllocationAllowed.is_valid_for(ExecutionPartition::RealtimeCpu));
}
#[test]
fn given_network_allowed_contract_when_valid_for_async_worker_then_true() {
assert!(SafetyContract::NetworkAllowed.is_valid_for(ExecutionPartition::AsyncWorker));
}
#[test]
fn given_network_allowed_contract_when_valid_for_blocking_worker_then_false() {
assert!(!SafetyContract::NetworkAllowed.is_valid_for(ExecutionPartition::BlockingWorker));
}
#[test]
fn given_external_service_contract_when_valid_for_external_partition_then_true() {
assert!(SafetyContract::ExternalService.is_valid_for(ExecutionPartition::External));
}
#[test]
fn given_blocking_allowed_contract_when_valid_for_blocking_worker_then_true() {
assert!(SafetyContract::BlockingAllowed.is_valid_for(ExecutionPartition::BlockingWorker));
}
#[test]
fn given_blocking_allowed_contract_when_valid_for_async_worker_then_false() {
assert!(!SafetyContract::BlockingAllowed.is_valid_for(ExecutionPartition::AsyncWorker));
}
}