util: Add thread-safe c wrapper
This commit is contained in:
		
							
								
								
									
										48
									
								
								src/util.rs
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/util.rs
									
									
									
									
									
								
							@ -15,6 +15,7 @@ pub mod c {
 | 
				
			|||||||
    use std::os::raw::c_char;
 | 
					    use std::os::raw::c_char;
 | 
				
			||||||
    use std::rc::Rc;
 | 
					    use std::rc::Rc;
 | 
				
			||||||
    use std::str::Utf8Error;
 | 
					    use std::str::Utf8Error;
 | 
				
			||||||
 | 
					    use std::sync::{Arc, Mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // traits
 | 
					    // traits
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -128,6 +129,53 @@ pub mod c {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    impl<T> COpaquePtr for Wrapped<T> {}
 | 
					    impl<T> COpaquePtr for Wrapped<T> {}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Similar to Wrapped, except thread-safe.
 | 
				
			||||||
 | 
					    #[repr(transparent)]
 | 
				
			||||||
 | 
					    pub struct ArcWrapped<T>(*const Mutex<T>);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    impl<T> ArcWrapped<T> {
 | 
				
			||||||
 | 
					        pub fn new(value: T) -> Self {
 | 
				
			||||||
 | 
					            Self::wrap(Arc::new(Mutex::new(value)))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        pub fn wrap(state: Arc<Mutex<T>>) -> Self {
 | 
				
			||||||
 | 
					            Self(Arc::into_raw(state))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        /// Extracts the reference to the data.
 | 
				
			||||||
 | 
					        /// It may cause problems if attempted in more than one place
 | 
				
			||||||
 | 
					        pub unsafe fn unwrap(self) -> Arc<Mutex<T>> {
 | 
				
			||||||
 | 
					            Arc::from_raw(self.0)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// Creates a new Rc reference to the same data.
 | 
				
			||||||
 | 
					        /// Use for accessing the underlying data as a reference.
 | 
				
			||||||
 | 
					        pub fn clone_ref(&self) -> Arc<Mutex<T>> {
 | 
				
			||||||
 | 
					            // A bit dangerous: the Rc may be in use elsewhere
 | 
				
			||||||
 | 
					            let used_rc = unsafe { Arc::from_raw(self.0) };
 | 
				
			||||||
 | 
					            let rc = used_rc.clone();
 | 
				
			||||||
 | 
					            Arc::into_raw(used_rc); // prevent dropping the original reference
 | 
				
			||||||
 | 
					            rc
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    impl<T> Clone for ArcWrapped<T> {
 | 
				
			||||||
 | 
					        fn clone(&self) -> Self {
 | 
				
			||||||
 | 
					            Self::wrap(self.clone_ref())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// ToOwned won't work here
 | 
				
			||||||
 | 
					    impl<T: Clone> CloneOwned for ArcWrapped<T> {
 | 
				
			||||||
 | 
					        type Owned = T;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fn clone_owned(&self) -> T {
 | 
				
			||||||
 | 
					            let rc = self.clone_ref();
 | 
				
			||||||
 | 
					            // FIXME: this panic here is inelegant.
 | 
				
			||||||
 | 
					            // It will only happen in case of crashes elsewhere, but still.
 | 
				
			||||||
 | 
					            let r = rc.lock().unwrap();
 | 
				
			||||||
 | 
					            r.to_owned()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Clones the underlying data structure, like ToOwned.
 | 
					/// Clones the underlying data structure, like ToOwned.
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user