Reputation: 3196
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?
Upvotes: 1
Views: 609
Reputation: 90872
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.
Upvotes: 2