Skip to content

Instantly share code, notes, and snippets.

@allada
Created July 1, 2024 18:12
Show Gist options
  • Save allada/27f23fb613956db0cc00752cb3b43532 to your computer and use it in GitHub Desktop.
Save allada/27f23fb613956db0cc00752cb3b43532 to your computer and use it in GitHub Desktop.
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum PriorityActionStage {
// Note: These are ordered by priority with the items that need to be
// processed first at the top (highest number).
Unknown = 0,
CompletedFromCache = 1,
Completed = 2,
Executing = 3,
Queued = 4,
CacheCheck = 5,
}
impl From<&ActionStage> for PriorityActionStage {
fn from(stage: &ActionStage) -> Self {
match stage {
ActionStage::CacheCheck => Self::CacheCheck,
ActionStage::Queued => Self::Queued,
ActionStage::Executing => Self::Executing,
ActionStage::Completed(_) => Self::Completed,
ActionStage::CompletedFromCache(_) => Self::CompletedFromCache,
ActionStage::Unknown => Self::Unknown,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
struct AwaitedActionSortKey(u64);
impl AwaitedActionSortKey {
const fn new(state_priority: PriorityActionStage, priority: i32, hash: [u8; 3]) -> Self {
let state_priority = state_priority as u8 as u64;
// Shift `new_priority` so [`i32::MIN`] is represented by zero.
// This makes it so any nagative values are positive, but
// maintains ordering.
const MIN_I32: i64 = (i32::MIN as i64).abs();
let priority = (priority as i64 + MIN_I32) as u64;
// The left 4 bits are the state priority, the next 32 bits are the
// priority, and the right 28 bits are the hash.
let hash = u64::from_be_bytes([0, 0, 0, 0, 0, hash[0], hash[1], hash[2]]);
let final_priority = (state_priority << 56) | (priority << 24) | hash;
AwaitedActionSortKey(final_priority)
}
fn new_with_action_hash(state_priority: PriorityActionStage, priority: i32, action_hash: &ActionInfoHashKey) -> Self {
let hash = {
let mut hasher = DefaultHasher::new();
ActionInfoHashKey::hash(action_hash, &mut hasher);
hasher.finish().to_le_bytes()[0..3].try_into().unwrap()
};
Self::new(state_priority, priority, hash)
}
}
// Ensure the size of the sort key is the same as a `u64`.
assert_eq_size!(AwaitedActionSortKey, u64);
// Note: Result has 0x3456789a + 0x80000000 = 0xb456789a because we need
// to shift the `i32::MIN` value to be represented by zero.
const_assert_eq!(AwaitedActionSortKey::new(PriorityActionStage::Queued, 0x3456789a, [0xbc, 0xde, 0xf0]).0, AwaitedActionSortKey(0x04b456789abcdef0).0);
// Ensure PriorityActionStage is used as the sort key first.
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::CacheCheck, i32::MIN, [0; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MAX, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MIN, [0; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Executing, i32::MAX, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Executing, i32::MIN, [0; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Completed, i32::MAX, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Completed, i32::MIN, [0; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::CompletedFromCache, i32::MAX, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::CompletedFromCache, i32::MIN, [0; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Unknown, i32::MAX, [0; 3]).0);
// Ensure the priority is used as the sort key second.
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MAX, [0xff; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MAX - 1, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MAX - 1, [0xff; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, 1, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, 1, [0xff; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, 0, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, 0, [0xff; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, -1, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, -1, [0xff; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MIN + 1, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MIN + 1, [0xff; 3]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, i32::MIN, [0; 3]).0);
// Ensure the hash is used as the sort key third.
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::CacheCheck, 0, [0xff, 0xff, 0xff]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, 0, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, 1, [0xff, 0xff, 0xff]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, 0, [0; 3]).0);
const_assert!(AwaitedActionSortKey::new(PriorityActionStage::Queued, 0, [0xff, 0xff, 0xff]).0 > AwaitedActionSortKey::new(PriorityActionStage::Queued, 0, [0; 3]).0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment