Created
February 26, 2018 09:12
-
-
Save shadowmint/a07efff191db93530b68af096d63f3b2 to your computer and use it in GitHub Desktop.
BackRef reference?
This file contains 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
use std::sync::Arc; | |
#[derive(PartialEq)] | |
enum SafePtrState { | |
Pending, | |
Resolved, | |
} | |
struct SafePtrData { | |
s1: SafePtrState, | |
s2: SafePtrState, | |
} | |
pub struct SafePtr { | |
lock: Arc<Box<SafePtrData>>, | |
owned_global_ref: *const SafePtrState, | |
} | |
impl SafePtr { | |
pub fn new() -> (SafePtr, SafePtr) { | |
let data = Box::new(SafePtrData { | |
s1: SafePtrState::Pending, | |
s2: SafePtrState::Pending, | |
}); | |
let rs1 = &data.s1 as *const SafePtrState; | |
let rs2 = &data.s1 as *const SafePtrState; | |
let arc1 = Arc::new(data); | |
let arc2 = arc1.clone(); | |
let p1 = SafePtr { | |
lock: arc1, | |
owned_global_ref: rs1, | |
}; | |
let p2 = SafePtr { | |
lock: arc2, | |
owned_global_ref: rs1, | |
}; | |
return (p1, p2); | |
} | |
/// This is safe because the state of owned_global_ref is valid on creation, | |
/// and the only way to modify it is with resolve(), which consumes the instance. | |
pub fn is_resolved(&self) -> bool { | |
unsafe { | |
let shared_ref = self.lock.as_ref(); | |
return shared_ref.s1 == SafePtrState::Resolved || shared_ref.s2 == SafePtrState::Resolved; | |
} | |
} | |
/// This is safe because it is the only way for any object to modify the reference. | |
/// The only other time mark_resolved() is called is in Drop, which cannot be hit if we are in this scope. | |
pub fn resolve(mut self) { | |
unsafe { | |
self.mark_resolved() | |
} | |
} | |
unsafe fn mark_resolved(&mut self) { | |
let owned_global_mut = &mut (*(self.owned_global_ref as *mut SafePtrState)); | |
*owned_global_mut = SafePtrState::Resolved; | |
} | |
} | |
impl Drop for SafePtr { | |
fn drop(&mut self) { | |
if !self.is_resolved() { | |
unsafe { | |
self.mark_resolved() | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment