Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic fn, channel, and thread spawn

I have this code here: (Playground link)

use std::thread;
use std::sync::mpsc::channel;

fn run<T: Send>(task: fn() -> T) -> T {
    let (tx, rx) = channel();
    thread::spawn(move || {
        tx.send(task());
    });
    rx.recv().unwrap()
}

fn main() {
    let task = || 1 + 2;

    let result = run(task);

    println!("{}", result);
}

But I'm getting a lifetime error I can't figure out.

<anon>:6:5: 6:18 error: the parameter type `T` may not live long enough [E0310]
<anon>:6     thread::spawn(move || {
             ^~~~~~~~~~~~~
<anon>:6:5: 6:18 help: consider adding an explicit lifetime bound `T: 'static`...
<anon>:6:5: 6:18 note: ...so that captured variable `tx` does not outlive the enclosing closure
<anon>:6     thread::spawn(move || {
             ^~~~~~~~~~~~~
<anon>:15:22: 15:26 error: mismatched types:
 expected `fn() -> _`,
    found `[closure <anon>:13:16: 13:24]`
(expected fn pointer,
    found closure) [E0308]
<anon>:15     let result = run(task);
                               ^~~~

Any suggestions? Thanks!

like image 524
jocull Avatar asked Jun 11 '15 02:06

jocull


1 Answers

The error message suggests adding a 'static bound to the type parameter T. If you do this, it will get rid of the first error:

fn run<T: Send + 'static>(task: fn() -> T) -> T

The 'static bound is needed to guarantee that the value returned by task can outlive the function where task runs. Read more about the 'static lifetime.

The second error is that you are passing a closure, while run expects a function pointer. One way to fix this is by changing task from a closure to a fn:

    fn task() -> u32 { 1 + 2 }

Here's the complete working code:

use std::thread;
use std::sync::mpsc::channel;

fn run<T: Send + 'static>(task: fn() -> T) -> T {
    let (tx, rx) = channel();
    thread::spawn(move || {
        tx.send(task());
    });
    rx.recv().unwrap()
}

fn main() {
    fn task() -> u32 { 1 + 2 }
    let result = run(task);
    println!("{}", result);
}
like image 121
mbrubeck Avatar answered Nov 16 '22 16:11

mbrubeck