diff --git a/src/lib.rs b/src/lib.rs
index 4513760..4aa72a9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,10 +11,6 @@ pub mod drop_guard;
pub mod ptr;
#[cfg(feature = "alloc")]
pub mod smallbox;
+pub mod util;
-pub const fn can_transmute() -> bool {
- use core::mem::{align_of, size_of};
- // We can transmute `A` to `B` iff `A` and `B` have the same size and the
- // alignment of `A` is greater than or equal to the alignment of `B`.
- size_of::() <= size_of::() && align_of::() >= align_of::()
-}
+pub use util::can_transmute;
diff --git a/src/util.rs b/src/util.rs
new file mode 100644
index 0000000..bcfc2c4
--- /dev/null
+++ b/src/util.rs
@@ -0,0 +1,48 @@
+use core::ops::{Deref, DerefMut};
+
+#[repr(transparent)]
+pub struct Send(pub(self) T);
+
+unsafe impl core::marker::Send for Send {}
+
+impl Deref for Send {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl DerefMut for Send {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+impl Send {
+ pub unsafe fn new(value: T) -> Self {
+ Self(value)
+ }
+}
+
+/// returns the number of available hardware threads, or 1 if it cannot be determined.
+#[cfg(feature = "std")]
+pub fn available_parallelism() -> usize {
+ std::thread::available_parallelism()
+ .map(|n| n.get())
+ .unwrap_or(1)
+}
+
+#[cfg(feature = "std")]
+pub fn unwrap_or_panic(result: std::thread::Result) -> T {
+ match result {
+ Ok(value) => value,
+ Err(payload) => std::panic::resume_unwind(payload),
+ }
+}
+
+pub const fn can_transmute() -> bool {
+ use core::mem::{align_of, size_of};
+ // We can transmute `A` to `B` iff `A` and `B` have the same size and the
+ // alignment of `A` is greater than or equal to the alignment of `B`.
+ size_of::() <= size_of::() && align_of::() >= align_of::()
+}