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

前端 未结 2 1956
醉酒成梦
醉酒成梦 2020-12-17 19:51

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

impl MyStruct {
    pub fn doSomething(&\'static self) {
        // Some          


        
相关标签:
2条回答
  • 2020-12-17 20:13

    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:

    • How do I create a global, mutable singleton?
    • How can you make a safe static singleton in Rust?

    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:

    • How do I use static lifetimes with threads?
    0 讨论(0)
  • 2020-12-17 20:30

    The naive way to do this is with a static variable, but it will require unsafe code if you need to actually set the value inside your main function:

    static mut OBJ: MyStruct = MyStruct;
    
    fn main() {
        unsafe {
            OBJ = MyStruct {};
            OBJ.doSomething();
        }
    }
    

    It's also unsafe to do pretty much anything with a mutable static thereafter.

    The much better way to do it is to let a library (lazy_static) take care of the unsafe code.

    #[macro_use]
    extern crate lazy_static;
    
    fn main() {
        lazy_static!{
            static ref OBJ: MyStruct = MyStruct {};
        }
        OBJ.doSomething();
    }
    
    0 讨论(0)
提交回复
热议问题