Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/reactor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,41 @@ pub use self::interval::Interval;
static NEXT_LOOP_ID: AtomicUsize = ATOMIC_USIZE_INIT;
scoped_thread_local!(static CURRENT_LOOP: Core);

struct CoreAndHandle {
core: RefCell<Core>,
handle: RefCell<Handle>
}

thread_local!(static DEFAULT_CORE_AND_HANDLE: CoreAndHandle = {
let core = Core::new().unwrap();
let handle = core.handle();
CoreAndHandle {
core: RefCell::new(core),
handle: RefCell::new(handle)
}
});

/// Get a mutable reference to the default core.
pub fn with_default_core<T, F: FnOnce(&mut Core) -> T>(cls: F) -> T {
DEFAULT_CORE_AND_HANDLE.with(|o|
cls(&mut *o.core.try_borrow_mut().expect(
"could not borrow default core, already borrowed (event loop running?)"
))
)
}

/// Shortcut for runnign the default event loop. Takes a future, which is passed
/// to Core::run (see docs there).
pub fn run_default<F>(f: F) -> Result<F::Item, F::Error>
where F: Future {
with_default_core(|core| core.run(f))
}

/// Get a handle to the default event loop.
pub fn default_handle() -> Handle {
DEFAULT_CORE_AND_HANDLE.with(|o| o.handle.borrow().clone())
}

/// An event loop.
///
/// The event loop is the main source of blocking in an application which drives
Expand Down
50 changes: 50 additions & 0 deletions tests/default-core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
extern crate tokio_core;
use tokio_core::reactor;

extern crate futures;
use futures::empty;
use futures::future::Future;

use std::thread;
use std::time::Duration;

#[test]
fn default_core() {

let val = 10;

let timeout = reactor::Timeout::new(
Duration::from_millis(10),
&reactor::default_handle()
).unwrap().map(|_| val);

let result = reactor::with_default_core(|core| core.run(timeout));

assert_eq!(result.unwrap(), val);
}

#[test]
fn default_core_in_another_thread() {
thread::spawn(move || {
let val = 10;

let timeout = reactor::Timeout::new(
Duration::from_millis(10),
&reactor::default_handle()
).unwrap().map(|_| val);

let result = reactor::run_default(timeout);

assert_eq!(result.unwrap(), val);
}).join();
}

#[test]
#[should_panic(expected = "could not borrow default core, already borrowed (event loop running?)")]
fn running_core_inside_running_core_panics() {
reactor::default_handle().spawn(reactor::Timeout::new(
Duration::from_millis(50),
&reactor::default_handle()
).unwrap().then(|_| reactor::run_default(empty::<(), ()>())));
reactor::run_default(empty::<(), ()>());
}