summaryrefslogtreecommitdiff
path: root/src/thread/scope.rst
blob: 09319cb9b70e6a3f663d0b5a5ce2074ae6898abd (plain)
use std::marker::PhantomData;

use crate::{Keyable, ThreadKey};

use super::{Scope, ScopedJoinHandle};

pub fn scope<'env, F, T>(key: impl Keyable, f: F) -> T
where
	F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
{
	let scope = Scope(PhantomData);
	let t = f(&scope);
	drop(key);
	t
}

impl<'scope> Scope<'scope, '_> {
	#[allow(clippy::unused_self)]
	pub fn spawn<T: Send + 'scope>(
		&self,
		f: impl FnOnce(ThreadKey) -> T + Send + 'scope,
	) -> std::io::Result<ScopedJoinHandle<'scope, T>> {
		unsafe {
			// safety: the lifetimes ensure that the data lives long enough
			let handle = std::thread::Builder::new().spawn_unchecked(|| {
				// safety: the thread just started, so the key cannot be acquired yet
				let key = ThreadKey::get().unwrap_unchecked();
				f(key)
			})?;

			Ok(ScopedJoinHandle {
				handle,
				_phantom: PhantomData,
			})
		}
	}
}

impl<T> ScopedJoinHandle<'_, T> {
	pub fn is_finished(&self) -> bool {
		self.handle.is_finished()
	}

	pub fn join(self) -> std::thread::Result<T> {
		self.handle.join()
	}
}