summaryrefslogtreecommitdiff
path: root/src/thread/scope.rst
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread/scope.rst')
-rw-r--r--src/thread/scope.rst47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/thread/scope.rst b/src/thread/scope.rst
new file mode 100644
index 0000000..09319cb
--- /dev/null
+++ b/src/thread/scope.rst
@@ -0,0 +1,47 @@
+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()
+ }
+}