mirror of
https://github.com/penpot/penpot.git
synced 2026-05-14 12:34:10 +00:00
♻️ Remove Mutex from mem buffer (#9479)
This commit is contained in:
parent
f62ee7d1ae
commit
64f73ef23b
@ -1,61 +1,73 @@
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::error::{Error, Result, CRITICAL_ERROR};
|
||||
use crate::{error::Result, performance};
|
||||
|
||||
pub const LAYOUT_ALIGN: usize = 4;
|
||||
|
||||
pub static BUFFERU8: Mutex<Option<Vec<u8>>> = Mutex::new(None);
|
||||
pub static BUFFER_ERROR: Mutex<u8> = Mutex::new(0x00);
|
||||
// Please, read about the #[allow(static_mut_refs)]
|
||||
//
|
||||
// If we don't put this allow, the compiler shows a warning like this:
|
||||
//
|
||||
// shared references to mutable statics are dangerous; it's undefined behavior
|
||||
// if the static is mutated or if a mutable reference is created for it while
|
||||
// the shared reference lives
|
||||
//
|
||||
// https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html
|
||||
//
|
||||
// But this isn't a problem in a single-threaded environment like WebAssembly
|
||||
// because access/modification is always sequential, not parallel.
|
||||
pub static mut BUFFERU8: Option<Vec<u8>> = None;
|
||||
pub static mut BUFFER_ERROR: u8 = 0x00;
|
||||
|
||||
pub fn clear_error_code() {
|
||||
let mut guard = BUFFER_ERROR.lock().unwrap();
|
||||
*guard = 0x00;
|
||||
unsafe {
|
||||
BUFFER_ERROR = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the error buffer from a byte. Used by #[wasm_error] when E: Into<u8>.
|
||||
pub fn set_error_code(code: u8) {
|
||||
let mut guard = BUFFER_ERROR.lock().unwrap();
|
||||
*guard = code;
|
||||
unsafe {
|
||||
BUFFER_ERROR = code;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn read_error_code() -> u8 {
|
||||
if let Ok(guard) = BUFFER_ERROR.lock() {
|
||||
*guard
|
||||
} else {
|
||||
CRITICAL_ERROR
|
||||
}
|
||||
unsafe { BUFFER_ERROR }
|
||||
}
|
||||
|
||||
pub fn write_bytes(mut bytes: Vec<u8>) -> *mut u8 {
|
||||
let mut guard = BUFFERU8.lock().unwrap();
|
||||
unsafe {
|
||||
performance::begin_measure!("write_bytes");
|
||||
#[allow(static_mut_refs)]
|
||||
if BUFFERU8.is_some() {
|
||||
panic!("Bytes already allocated");
|
||||
}
|
||||
|
||||
if guard.is_some() {
|
||||
panic!("Bytes already allocated");
|
||||
let ptr = bytes.as_mut_ptr();
|
||||
BUFFERU8 = Some(bytes);
|
||||
performance::end_measure!("write_bytes");
|
||||
ptr
|
||||
}
|
||||
|
||||
let ptr = bytes.as_mut_ptr();
|
||||
|
||||
*guard = Some(bytes);
|
||||
ptr
|
||||
}
|
||||
|
||||
pub fn bytes() -> Vec<u8> {
|
||||
let mut guard = BUFFERU8.lock().unwrap();
|
||||
guard.take().expect("Buffer is not initialized")
|
||||
unsafe {
|
||||
#[allow(static_mut_refs)]
|
||||
BUFFERU8.take().expect("Buffer is not initialized")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_or_empty() -> Vec<u8> {
|
||||
let mut guard = BUFFERU8.lock().unwrap();
|
||||
guard.take().unwrap_or_default()
|
||||
unsafe {
|
||||
#[allow(static_mut_refs)]
|
||||
BUFFERU8.take().unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn free_bytes() -> Result<()> {
|
||||
let mut guard = BUFFERU8
|
||||
.lock()
|
||||
.map_err(|_| Error::CriticalError("Failed to lock buffer".to_string()))?;
|
||||
*guard = None;
|
||||
std::mem::drop(guard);
|
||||
unsafe {
|
||||
BUFFERU8 = None;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -9,15 +9,22 @@ use macros::wasm_error;
|
||||
#[no_mangle]
|
||||
#[wasm_error]
|
||||
pub extern "C" fn alloc_bytes(len: usize) -> Result<*mut u8> {
|
||||
let mut guard = BUFFERU8
|
||||
.lock()
|
||||
.map_err(|_| Error::CriticalError("Failed to lock buffer".to_string()))?;
|
||||
|
||||
if guard.is_some() {
|
||||
return Err(Error::CriticalError("Bytes already allocated".to_string()));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// If we don't put this allow, the compiler shows a warning like this:
|
||||
//
|
||||
// shared references to mutable statics are dangerous; it's undefined behavior
|
||||
// if the static is mutated or if a mutable reference is created for it while
|
||||
// the shared reference lives
|
||||
//
|
||||
// https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html
|
||||
//
|
||||
// But this isn't a problem in a single-threaded environment like WebAssembly
|
||||
// because access/modification is always sequential, not parallel.
|
||||
#[allow(static_mut_refs)]
|
||||
if BUFFERU8.is_some() {
|
||||
return Err(Error::CriticalError("Bytes already allocated".to_string()));
|
||||
}
|
||||
|
||||
let layout = Layout::from_size_align_unchecked(len, LAYOUT_ALIGN);
|
||||
let ptr = alloc(layout);
|
||||
if ptr.is_null() {
|
||||
@ -25,7 +32,7 @@ pub extern "C" fn alloc_bytes(len: usize) -> Result<*mut u8> {
|
||||
}
|
||||
// TODO: Maybe this could be removed.
|
||||
ptr::write_bytes(ptr, 0, len);
|
||||
*guard = Some(Vec::from_raw_parts(ptr, len, len));
|
||||
BUFFERU8 = Some(Vec::from_raw_parts(ptr, len, len));
|
||||
Ok(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user