summaryrefslogtreecommitdiffstats
path: root/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs')
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs
new file mode 100644
index 000000000..2128e93cb
--- /dev/null
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs
@@ -0,0 +1,125 @@
+// Copyright 2016 Amanieu d'Antras
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use cfg_if::cfg_if;
+use core::{
+ arch::wasm32,
+ sync::atomic::{AtomicI32, Ordering},
+};
+use instant::Instant;
+use std::time::Duration;
+use std::{convert::TryFrom, thread};
+
+cfg_if! {
+ if #[cfg(all(
+ target_arch = "wasm32",
+ target_os = "unknown",
+ target_vendor = "unknown"
+ ))] {
+ // This function serves as a polyfill for `Instant::checked_duration_since`, which is
+ // currently not implemented for wasm32-unknown-unknown.
+ // TODO: Remove this shim once it
+ fn checked_duration_since_now(other: Instant) -> Option<Duration> {
+ let now = Instant::now();
+
+ if other < now {
+ None
+ } else {
+ Some(other.duration_since(now))
+ }
+ }
+ } else {
+ // If we are not targeting wasm32, we can use the native `checked_duration_since`.
+ fn checked_duration_since_now(timeout: Instant) -> Option<Duration> {
+ timeout.checked_duration_since(Instant::now())
+ }
+ }
+}
+
+// Helper type for putting a thread to sleep until some other thread wakes it up
+pub struct ThreadParker {
+ parked: AtomicI32,
+}
+
+const UNPARKED: i32 = 0;
+const PARKED: i32 = 1;
+
+impl super::ThreadParkerT for ThreadParker {
+ type UnparkHandle = UnparkHandle;
+
+ const IS_CHEAP_TO_CONSTRUCT: bool = true;
+
+ #[inline]
+ fn new() -> ThreadParker {
+ ThreadParker {
+ parked: AtomicI32::new(UNPARKED),
+ }
+ }
+
+ #[inline]
+ unsafe fn prepare_park(&self) {
+ self.parked.store(PARKED, Ordering::Relaxed);
+ }
+
+ #[inline]
+ unsafe fn timed_out(&self) -> bool {
+ self.parked.load(Ordering::Relaxed) == PARKED
+ }
+
+ #[inline]
+ unsafe fn park(&self) {
+ while self.parked.load(Ordering::Acquire) == PARKED {
+ let r = wasm32::memory_atomic_wait32(self.ptr(), PARKED, -1);
+ // we should have either woken up (0) or got a not-equal due to a
+ // race (1). We should never time out (2)
+ debug_assert!(r == 0 || r == 1);
+ }
+ }
+
+ #[inline]
+ unsafe fn park_until(&self, timeout: Instant) -> bool {
+ while self.parked.load(Ordering::Acquire) == PARKED {
+ if let Some(left) = checked_duration_since_now(timeout) {
+ let nanos_left = i64::try_from(left.as_nanos()).unwrap_or(i64::max_value());
+ let r = wasm32::memory_atomic_wait32(self.ptr(), PARKED, nanos_left);
+ debug_assert!(r == 0 || r == 1 || r == 2);
+ } else {
+ return false;
+ }
+ }
+ true
+ }
+
+ #[inline]
+ unsafe fn unpark_lock(&self) -> UnparkHandle {
+ // We don't need to lock anything, just clear the state
+ self.parked.store(UNPARKED, Ordering::Release);
+ UnparkHandle(self.ptr())
+ }
+}
+
+impl ThreadParker {
+ #[inline]
+ fn ptr(&self) -> *mut i32 {
+ &self.parked as *const AtomicI32 as *mut i32
+ }
+}
+
+pub struct UnparkHandle(*mut i32);
+
+impl super::UnparkHandleT for UnparkHandle {
+ #[inline]
+ unsafe fn unpark(self) {
+ let num_notified = wasm32::memory_atomic_notify(self.0 as *mut i32, 1);
+ debug_assert!(num_notified == 0 || num_notified == 1);
+ }
+}
+
+#[inline]
+pub fn thread_yield() {
+ thread::yield_now();
+}