Skip to content

Instantly share code, notes, and snippets.

@gterzian
Last active June 15, 2023 07:07
Show Gist options
  • Save gterzian/a774516057de30f7a8aa9d4dbfc4cbd0 to your computer and use it in GitHub Desktop.
Save gterzian/a774516057de30f7a8aa9d4dbfc4cbd0 to your computer and use it in GitHub Desktop.
fn example_with_sequential_mutices(my_thread_mutex_permission: OuterMutexPermission) {
// We have three sequential mutices. The type system ensures we always
// claim A then B then C, never C then B then A.
let can_safely_read = Arc::new(DeadlockProofMutex::new(false, unique_type!()));
let mutex1 = Arc::new(DeadlockProofMutex::new(0, unique_type!()));
let mutex2 = Arc::new(DeadlockProofMutex::new(0, unique_type!()));
let mutex3 = Arc::new(DeadlockProofMutex::new(0, unique_type!()));
let c_mutex1 = Arc::clone(&mutex1);
let c_mutex2 = Arc::clone(&mutex2);
let c_mutex3 = Arc::clone(&mutex3);
thread::spawn(move || {
let mutex_permission = OuterMutexPermission::get();
let mut guard = c_mutex1.lock(mutex_permission).unwrap();
*guard = 10;
let next_permission = guard.unlock_for_sequential();
// We now have permission to unlock mutex2
let mut guard2 = c_mutex2.lock(next_permission).unwrap();
*guard2 = 20;
let next_permission = guard2.unlock_for_sequential();
// We now have permission to unlock mutex3
let mut guard3 = c_mutex3.lock(next_permission).unwrap();
*guard3 = 30;
// Explicitly unlock, to show how to get back to the
// outermost mutex in case we need to claim something else.
let _mutex_permission = guard3.unlock().to_earlier().to_earlier();
})
.join()
.expect("thread::spawn failed");
let can_safely_read = can_safely_read.lock(my_thread_mutex_permission).unwrap();
assert!(*can_safely_read);
// The type system will now insist we claim and release the mutices in the
// same order.
let guard = mutex1.lock(can_safely_read.unlock()).unwrap();
assert_eq!(*guard, 10);
let next_permission = guard.unlock_for_sequential();
let guard2 = mutex2.lock(next_permission).unwrap();
assert_eq!(*guard2, 20);
let next_permission = guard2.unlock_for_sequential();
let guard3 = mutex3.lock(next_permission).unwrap();
assert_eq!(*guard3, 30);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment