Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

rust - How do I call a function that requires a 'static lifetime with a variable created in main?

I've got a struct defined that has a function which defines a static lifetime:

impl MyStruct {
    pub fn doSomething(&'static self) {
        // Some code goes here
    }
}

I'm consuming it from main like so:

fn main() {
    let obj = MyStruct {};
    obj.doSomething();
}

It's intended for the doSomething call to block and execute for the lifetime of the application.

I'm running into issues with the lifetime checks where it's stating that it may outlive the main function, which seems strange to me as once main is complete the application should exit.

Is there a way to achieve this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The primary way to create a reference that has the 'static lifetime is to make the variable static. A static variable is one that can be created at compile time:

struct MyStruct;

impl MyStruct {
    pub fn do_something(&'static self) {}
}

static OBJ: MyStruct = MyStruct;

fn main() {
    OBJ.do_something();
}

As Rust's constant evaluation story improves, this will be more common, but it will never allow configuration at runtime.

A far less common method is to deliberately leak memory, producing a reference that will last "forever". This should be discouraged because leaking memory isn't a good thing:

fn main() {
    let obj = Box::leak(Box::new(MyStruct));
    obj.do_something();
}

There's also the possibility of creating a singleton:

as once main is complete the application should exit.

Perhaps, but the compiler doesn't treat main specially for lifetime purposes.


hyper requires a static runtime when running the server and processing each request.

No, it doesn't. It has a bound of : 'static, which means that any references passed in must be 'static, but you don't have to pass in a bare reference at all.

For patterns like this, the most common thing is to pass in something like an Arc. This allows sharing of the underlying resource.

pub fn do_something<F, T>(f: F)
where
    F: Fn() -> T + 'static,
    T: 'static,
{
    // "spawn" 3 threads
    f();
    f();
    f();
}

struct MyStruct;

static OBJ: MyStruct = MyStruct;

fn main() {
    // OK
    do_something(|| &OBJ);

    // Not OK
    let another = MyStruct;
    do_something(|| &another);

    // OK
    use std::sync::Arc;
    let shared = Arc::new(MyStruct);
    do_something(move || shared.clone());
}

You can even use interior mutability if you wanted dynamic reconfiguration.

See also:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...