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::rc::Rc;
|
||||
use std::str::Utf8Error;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// traits
|
||||
|
||||
@ -128,6 +129,53 @@ pub mod c {
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user