script_bindings/lock.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::sync::OnceLock;
6
7/// A OnceLock wrapping a type that is not considered threadsafe by the Rust compiler, but
8/// will be used in a threadsafe manner (it will not be mutated, after being initialized).
9///
10/// This is needed to allow using JS API types (which usually involve raw pointers) in static initializers,
11/// when Servo guarantees through the use of OnceLock that only one thread will ever initialize
12/// the value.
13pub struct ThreadUnsafeOnceLock<T>(OnceLock<T>);
14
15impl<T> ThreadUnsafeOnceLock<T> {
16 #[allow(clippy::new_without_default)]
17 pub const fn new() -> Self {
18 Self(OnceLock::new())
19 }
20
21 /// Initialize the value inside this lock. Panics if the lock has been previously initialized.
22 pub fn set(&self, val: T) {
23 assert!(self.0.set(val).is_ok());
24 }
25
26 /// Get a reference to the value inside this lock. Panics if the lock has not been initialized.
27 ///
28 /// # Safety
29 /// The caller must ensure that it does not mutate value contained inside this lock
30 /// (using interior mutability).
31 pub unsafe fn get(&self) -> &T {
32 self.0.get().unwrap()
33 }
34}
35
36unsafe impl<T> Sync for ThreadUnsafeOnceLock<T> {}
37unsafe impl<T> Send for ThreadUnsafeOnceLock<T> {}