/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! A rust helper to ease the use of Gecko's refcounted types.
usecrate::gecko_bindings::{bindings, structs}; usecrate::Atom; use servo_arc::Arc; use std::fmt::Write; use std::marker::PhantomData; use std::ops::Deref; use std::{fmt, mem, ptr};
/// Trait for all objects that have Addref() and Release /// methods and can be placed inside RefPtr<T> pubunsafetrait RefCounted { /// Bump the reference count. fn addref(&self); /// Decrease the reference count. unsafefn release(&self);
}
/// Trait for types which can be shared across threads in RefPtr. pubunsafetrait ThreadSafeRefCounted: RefCounted {}
/// A custom RefPtr implementation to take into account Drop semantics and /// a bit less-painful memory management. pubstruct RefPtr<T: RefCounted> {
ptr: *mut T,
_marker: PhantomData<T>,
}
impl<T: RefCounted> RefPtr<T> { /// Create a new RefPtr from an already addrefed pointer obtained from FFI. /// /// The pointer must be valid, non-null and have been addrefed. pubunsafefn from_addrefed(ptr: *mut T) -> Self {
debug_assert!(!ptr.is_null());
RefPtr {
ptr,
_marker: PhantomData,
}
}
/// Returns whether the current pointer is null. pubfn is_null(&self) -> bool { self.ptr.is_null()
}
/// Create a new RefPtr from a pointer obtained from FFI. /// /// This method calls addref() internally pubunsafefn new(ptr: *mut T) -> Self { let ret = RefPtr {
ptr,
_marker: PhantomData,
};
ret.addref();
ret
}
/// Produces an FFI-compatible RefPtr that can be stored in style structs. /// /// structs::RefPtr does not have a destructor, so this may leak pubfn forget(self) -> structs::RefPtr<T> { let ret = structs::RefPtr {
mRawPtr: self.ptr,
_phantom_0: PhantomData,
};
mem::forget(self);
ret
}
/// Returns the raw inner pointer to be fed back into FFI. pubfn get(&self) -> *mut T { self.ptr
}
/// Addref the inner data, obviously leaky on its own. pubfn addref(&self) { if !self.ptr.is_null() { unsafe {
(*self.ptr).addref();
}
}
}
/// Release the inner data. /// /// Call only when the data actually needs releasing. pubunsafefn release(&self) { if !self.ptr.is_null() {
(*self.ptr).release();
}
}
}
impl<T: RefCounted> structs::RefPtr<T> { /// Produces a Rust-side RefPtr from an FFI RefPtr, bumping the refcount. /// /// Must be called on a valid, non-null structs::RefPtr<T>. pubunsafefn to_safe(&self) -> RefPtr<T> { let r = RefPtr {
ptr: self.mRawPtr,
_marker: PhantomData,
};
r.addref();
r
} /// Produces a Rust-side RefPtr, consuming the existing one (and not bumping /// the refcount). pubunsafefn into_safe(self) -> RefPtr<T> {
debug_assert!(!self.mRawPtr.is_null());
RefPtr {
ptr: self.mRawPtr,
_marker: PhantomData,
}
}
/// Replace a structs::RefPtr<T> with a different one, appropriately /// addref/releasing. /// /// Both `self` and `other` must be valid, but can be null. /// /// Safe when called on an aliased pointer because the refcount in that case /// needs to be at least two. pubunsafefn set(&mutself, other: &Self) { self.clear(); if !other.mRawPtr.is_null() {
*self = other.to_safe().forget();
}
}
/// Clear an instance of the structs::RefPtr<T>, by releasing /// it and setting its contents to null. /// /// `self` must be valid, but can be null. pubunsafefn clear(&mutself) { if !self.mRawPtr.is_null() {
(*self.mRawPtr).release(); self.mRawPtr = ptr::null_mut();
}
}
/// Replace a `structs::RefPtr<T>` with a `RefPtr<T>`, /// consuming the `RefPtr<T>`, and releasing the old /// value in `self` if necessary. /// /// `self` must be valid, possibly null. pubfn set_move(&mutself, other: RefPtr<T>) { if !self.mRawPtr.is_null() { unsafe {
(*self.mRawPtr).release();
}
}
*self = other.forget();
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.