Skip to content

Commit

Permalink
Remove some unsafe code (bevyengine#540)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stjepan Glavina authored and mrk-its committed Oct 6, 2020
1 parent d4a365e commit 9e091ba
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 25 deletions.
19 changes: 4 additions & 15 deletions crates/bevy_tasks/src/single_threaded_task_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,8 @@ impl TaskPool {
{
let executor = async_executor::LocalExecutor::new();

let executor: &async_executor::LocalExecutor = &executor;
let executor: &'scope async_executor::LocalExecutor = unsafe { mem::transmute(executor) };

let mut scope = Scope {
executor,
executor: &executor,
results: Vec::new(),
};

Expand All @@ -87,26 +84,18 @@ impl TaskPool {
}

pub struct Scope<'scope, T> {
executor: &'scope async_executor::LocalExecutor,
executor: &'scope async_executor::LocalExecutor<'scope>,
// Vector to gather results of all futures spawned during scope run
results: Vec<Arc<Mutex<Option<T>>>>,
}

impl<'scope, T: Send + 'static> Scope<'scope, T> {
impl<'scope, T: Send + 'scope> Scope<'scope, T> {
pub fn spawn<Fut: Future<Output = T> + 'scope + Send>(&mut self, f: Fut) {
let result = Arc::new(Mutex::new(None));
self.results.push(result.clone());
let f = async move {
result.lock().unwrap().replace(f.await);
};

// SAFETY: This function blocks until all futures complete, so we do not read/write the
// data from futures outside of the 'scope lifetime. However, rust has no way of knowing
// this so we must convert to 'static here to appease the compiler as it is unable to
// validate safety.
let fut: Pin<Box<dyn Future<Output = ()> + 'scope>> = Box::pin(f);
let fut: Pin<Box<dyn Future<Output = ()> + 'static>> = unsafe { mem::transmute(fut) };

self.executor.spawn(fut).detach();
self.executor.spawn(f).detach();
}
}
5 changes: 2 additions & 3 deletions crates/bevy_tasks/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ impl<T> Task<T> {
impl<T> Future for Task<T> {
type Output = T;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// Safe because Task is pinned and contains async_executor::Task by value
unsafe { self.map_unchecked_mut(|x| &mut x.0).poll(cx) }
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.0).poll(cx)
}
}
10 changes: 3 additions & 7 deletions crates/bevy_tasks/src/task_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
thread::{self, JoinHandle},
};

use futures_lite::future;
use futures_lite::{future, pin};

/// Used to create a TaskPool
#[derive(Debug, Default, Clone)]
Expand Down Expand Up @@ -180,12 +180,8 @@ impl TaskPool {
results
};

// Move the value to ensure that it is owned
let mut fut = fut;

// Shadow the original binding so that it can't be directly accessed
// ever again.
let fut = unsafe { Pin::new_unchecked(&mut fut) };
// Pin the future on the stack.
pin!(fut);

// SAFETY: This function blocks until all futures complete, so we do not read/write the
// data from futures outside of the 'scope lifetime. However, rust has no way of knowing
Expand Down

0 comments on commit 9e091ba

Please sign in to comment.