Skip to content

kituyiharry/rustasync-futures

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rust async-await

A Rust demo program showing the basic components of asynchrony in the language i.e I made this just to build an intuition on how rust futures work

  1. Future: A Unit of computation
struct TimerFuture {
	shared_state: Arc<Mutex<SharedState>>,
}

struct SharedState {
	completed: bool,
	waker: Option<Waker>,
}

impl Future for TimerFuture {
	type Output = ();
	fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
		let mut shared_state = self.shared_state.lock().unwrap();
		if shared_state.completed {
			Poll::Ready(())
		} else {
			// Create the waker
			shared_state.waker = Some(cx.waker().clone());
			Poll::Pending
		}
	}
}

impl TimerFuture {
	pub fn new(duration: Duration) -> Self {
		let shared_state = Arc::new(Mutex::new(SharedState {
		completed: false,
		waker: None,
	}));
	...
	TimerFuture { shared_state }
}
  1. Executor: Offloads work off a queue and runs them
struct Executor {
	ready_queue: Receiver<Arc<Task>>,
}

impl Executor {
	fn run(&self) {
		while let Ok(task) = self.ready_queue.recv() {
			.....
		}
	}
}
  1. Reactor: Executes tasks are ready to execute, Basically how you react when you (the task) are awakened
impl ArcWake for Task {
	fn wake_by_ref(arc_self: &Arc<Self>) {
		let cloned = arc_self.clone();
		...
		arc_self.task_sender.send(cloned).expect("too many tasks queued")
	}
}
  1. Generator(stackless routines) : Currently unstable
// Just to understand generators!
fn genums() -> impl std::ops::Generator<Yield = u32, Return = ()> {
	|| {
		let xs: Vec<u32> = (1..10).collect();
		...
		yield sum;
	}
}
  1. Spawner : Spawns new stuff onto the executor!
#[derive(Clone)]
struct Spawner {
	task_sender: SyncSender<Arc<Task>>,
}

fn new_executor_and_spawner() -> (Executor, Spawner) {
	// Max allowable tasks on the Queue
	const MAX_Q_TASKS: usize = 10_000;
	let (task_sender, ready_queue) = sync_channel(MAX_Q_TASKS);
	(Executor { ready_queue }, Spawner { task_sender })
}
  1. Task : A chain of futures or Unit of work
// A future can reschedule itself to be polled by an executor
struct Task {
	// In progress future to be pushed to completion
	future: Mutex<Option<BoxFuture<'static, ()>>>,
	// Handle to place task itself back onto the task queue
	task_sender: SyncSender<Arc<Task>>,
}

Adapted from : This talk and This sources

Usage

Use the following commands

$ cargo build
$ cargo run

About

Intuition around async-await in rust

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages