Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tokio_core::reactor::Core can't be stored in a global variable #75

Closed
rushmorem opened this issue Oct 24, 2016 · 5 comments
Closed

tokio_core::reactor::Core can't be stored in a global variable #75

rushmorem opened this issue Oct 24, 2016 · 5 comments

Comments

@rushmorem
Copy link

rushmorem commented Oct 24, 2016

It's my understanding that only one instance of tokio_core::reactor::Core should be used for the entire lifetime of the program so I think having this instance in a global variable would be nice. So I tried making this instance thread safe by wrapping it in a RwLock and storing it using lazy_static!:-

extern crate tokio_core;
#[macro_use] extern crate lazy_static;

use tokio_core::reactor::Core;
use std::sync::RwLock;

lazy_static! {
    static ref CORE: RwLock<Core> = RwLock::new(Core::new().unwrap());
}

However, this gives me the following error:-

error[E0277]: the trait bound `std::rc::Rc<std::cell::RefCell<tokio_core::reactor::Inner>>: std::marker::Send` is not satisfied
 --> <lazy_static macros>:2:32
  |
2 | use std :: sync :: ONCE_INIT ; static mut $ NAME : $ crate :: lazy :: Lazy < $
  |                                ^
<lazy_static macros>:21:1: 21:40 note: in this expansion of __lazy_static_create! (defined in <lazy_static macros>)
<lazy_static macros>:9:1: 10:74 note: in this expansion of lazy_static! (defined in <lazy_static macros>)
src/lib.rs:7:1: 9:2 note: in this expansion of lazy_static! (defined in <lazy_static macros>)
  |
  = note: `std::rc::Rc<std::cell::RefCell<tokio_core::reactor::Inner>>` cannot be sent between threads safely
  = note: required because it appears within the type `tokio_core::reactor::Core`
  = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::RwLock<tokio_core::reactor::Core>`
  = note: required by `lazy_static::lazy::Lazy`

[truncated]

This traces back to mio but I figured since @carllerche is also a member of this team it might be better to put it here.

@carllerche
Copy link
Member

You are correct that Core cannot be stored in a global. Core needs to be owned by the thread that is driving it. Instead, you can store a remote handle: reactor::Remote in a global variable and use that to interact with the reactor.

Hope this helps

@rushmorem
Copy link
Author

That is very helpful. Thanks!

@rushmorem
Copy link
Author

I can't figure out how to use this... Normally we need to:-

// Create an event loop
let mut core = Core::new().unwrap();

// Create a future using a handle to the event loop
let socket = TcpStream::connect(&addr, &core.handle());

// Do stuff with the future...

// And then actually run the future using `core.run()`
let (_, data) = core.run(response).unwrap();

I understand an instance to Handle will be passed to me when I call the spawn() method on the Remote so I can probably do:-

remote.spawn(|handle| {
    // Create a future using a handle to the event loop
    let socket = TcpStream::connect(&addr, handle);

    // Do stuff with the future...
});

How then do I actually perform the final step. That is, run the future?

@carllerche
Copy link
Member

So, there is a bit of boiler plate right now, I'll file an issue to track discussing it...

let (tx, rx) = futures::oneshot();

remote.spawn(|handle| {
    TcpStream::connect(&addr, handle)
        .and_then(|socket| {
            let resp = do_things_with_socket(socket);
            resp.and_then(|res| {
                tx.complete(res);
                Ok(())
            })
        })
});

let res = rx.wait();

@rushmorem
Copy link
Author

Awesome, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants