Add waker_fn (#18)

* Add waker_fn

* Add a waker_fn test

* Double sleep times

* More benches

* Prohibit recursive block_on calls

* Reformat code
diff --git a/examples/block.rs b/examples/block.rs
new file mode 100644
index 0000000..e4124b2
--- /dev/null
+++ b/examples/block.rs
@@ -0,0 +1,60 @@
+//! A simple implementation of `block_on`.
+
+use std::cell::RefCell;
+use std::future::Future;
+use std::task::{Context, Poll, Waker};
+use std::thread;
+use std::time::Duration;
+
+use crossbeam::sync::Parker;
+use futures::channel::oneshot;
+
+/// Runs a future to completion on the current thread.
+fn block_on<F: Future>(future: F) -> F::Output {
+    // Pin the future on the stack.
+    pin_utils::pin_mut!(future);
+
+    thread_local! {
+        // Parker and waker associated with the current thread.
+        static CACHE: RefCell<(Parker, Waker)> = {
+            let parker = Parker::new();
+            let unparker = parker.unparker().clone();
+            let waker = async_task::waker_fn(move || unparker.unpark());
+            RefCell::new((parker, waker))
+        };
+    }
+
+    CACHE.with(|cache| {
+        // Panic if `block_on()` is called recursively.
+        let (parker, waker) = &mut *cache.try_borrow_mut().ok().expect("recursive block_on()");
+
+        // Create the task context.
+        let cx = &mut Context::from_waker(&waker);
+
+        // Keep polling the future until completion.
+        loop {
+            match future.as_mut().poll(cx) {
+                Poll::Ready(output) => return output,
+                Poll::Pending => parker.park(),
+            }
+        }
+    })
+}
+
+fn main() {
+    let (s, r) = oneshot::channel();
+
+    // Spawn a thread that will send a message through the channel.
+    thread::spawn(move || {
+        thread::sleep(Duration::from_secs(1));
+        s.send("Hello, world!").unwrap();
+    });
+
+    // Block until the message is received.
+    let msg = block_on(async {
+        println!("Awaiting...");
+        r.await.unwrap()
+    });
+
+    println!("{}", msg);
+}