Last active
June 15, 2023 07:07
-
-
Save gterzian/a774516057de30f7a8aa9d4dbfc4cbd0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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