Passing a Vec<Struct> into a new task

巧了我就是萌 提交于 2019-12-11 11:37:12

问题


Im attempting to pass a Vector of a custom struct into a function that is executed in a new task. I've implemented the Clone trait, which I thought was needed for this, but apparently the vector I want to pass in needs to implement 'static+Send in order to be captured in the closure's environment. I'm not exactly sure how to go about satisfying those lifetime specs?

I'm attempting to start the process from this function

pub fn start(server: Server, ip: &str, port: u16) {

    // Other things happening

    spawn(proc() {
        event_loop(server.events.clone(), from_conn_pool)
    });
}

fn event_loop(events: Vec<Event>, from_conn_pool: Receiver<Vec<Socket>>) {
    // Wizard magic
}

The error I receive is: error: cannot capture variable of type rustic_io::server::Server<'_>, which does not fulfill 'static+Send, in a bounded closure

server.rs

pub struct Server<'a> {
    pub sockets: Vec<Socket<'a>>,
    pub events: Vec<Event<'a>>
}

event.rs

pub struct Event<'a> {
    pub name: String,
    pub execute: &'a fn(data: &str, server: super::Server)
}

impl<'a> Event<'a> {
    pub fn new(event: &str, execute: &'a fn(data: &str, server: super::Server)) -> Event<'a> {
        Event {
            name: String::from_str(event),
            execute: execute
        }
    }
}

impl<'a> Clone for Event<'a> {
    fn clone(&self) -> Event<'a> {
        Event {
            name: self.name.clone(),
            execute: self.execute
        }
    }
}

The event loop task will just loop over various streams and if data is read that matches a certain event name, it fires off the function associated with it. From the Rust documentation, I can see that you can start a named function off by calling spawn like so:

// Print something profound in a different task using a named function
fn print_message() { println!("I am running in a different task!"); }
spawn(print_message);

Which, I believe is the way I should be spawning the task, because it is a named function that is getting executed. Im assuming that because I'm calling it as spawn(proc(){ ... }), it is expecting everything going in to be closure-ownable? I've tried spawning the task as spawn(event_loop(arg, arg2)), but the compiler gives me: error: mismatched types: expected proc():Send but found () (expected fn but found ())

At this point, I've got no idea how to get that Vec<Event> into a new task?


回答1:


A proc() owns its environment. Anything coming into it must be able to be moved into it and must thus be 'static and Send.

This means that when you write

spawn(proc() {
    event_loop(server.events.clone(), from_conn_pool)
});

it is trying to capture server (because of server.events.clone()—note how it’s capturing the entire Server for this purpose; it’s unlikely to be what you wanted (you can do something like let events = server.events.clone(); before the proc and then use events, or you can just acknowledge that the clone() call is superfluous anyway) and from_conn_pool. Your problem is with server: it is not necessarily 'static, because you didn’t specify any lifetime for the type and so it is inferred as an arbitrary lifetime; that is, it may contain an event of non-static lifetime, which evidently can’t be moved to a new task. You would for starters need Server<'static>.

But the question then rises: why are you using &'a fn(…) rather than just fn(…) as your type? If you drop the whole reference thing there, your problem will go away.



来源:https://stackoverflow.com/questions/25286096/passing-a-vecstruct-into-a-new-task

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!