Проблемы с владением при попытке работать с переменными-членами, переданными в закрытие в методе-члене

Я пытаюсь инкапсулировать выполнение цикла обработки событий Glutin/winit в пользовательском классе, описанном в разделе примеров здесь: https://docs.rs/glutin/0.26.0/glutin/window/struct.Window.html

Теперь я столкнулся с проблемой обработки прав собственности на self членов при попытке получить к ним доступ в закрытии, переданном методу:

pub struct GameWindow {
    context: ContextWrapper<PossiblyCurrent, Window>,
    event_loop: EventLoop<()>,
    gl: Rc<gl::Gl>,
}

impl GameWindow {
    pub fn run(&self) {
        self.event_loop.run(move |event, _, control_flow| {
            *control_flow = ControlFlow::Poll;

            match event {
                Event::WindowEvent {
                    event: WindowEvent::CloseRequested,
                    ..
                } => {
                    *control_flow = ControlFlow::Exit;
                }
                Event::MainEventsCleared => {
                    unsafe {
                        self.gl.Clear(gl::COLOR_BUFFER_BIT);
                    }
                    self.context.swap_buffers().unwrap();
                }
                _ => (),
            }
        });
    }
}

Компилятор выдает следующую ошибку: self имеет анонимное время жизни '_, но должно удовлетворять требованию 'static времени жизни.

Применение этого предложения (хотя я еще не знаком со статическим временем жизни) приводит к ошибке при доступе к self.event_loop: невозможно выйти из цикла self.event_loop, который находится за общей ссылкой.

Как правильно решить эту проблему?


person Christian Ivicevic    schedule 01.05.2021    source источник
comment
Я полагаю, что вы пытаетесь обойти действительно небезопасный шаблон, который приведет к различного рода ошибкам, но, возможно, это может направить вас в правильном направлении. Как использовать статические времена жизни с потоками?   -  person Félix Adriyel Gagnon-Grenier    schedule 01.05.2021
comment
Я считаю, что логическая проблема здесь заключается в том, что нет никакой гарантии, что self все еще будет существовать, когда закрытие действительно выполнится.   -  person Félix Adriyel Gagnon-Grenier    schedule 01.05.2021
comment
EventLoop::run потребляет self. Вы должны владеть EventLoop (и, следовательно, GameWindow, который его содержит), чтобы вызывать его.   -  person AlphaModder    schedule 02.05.2021


Ответы (1)


Я решил эту конкретную проблему, сделав event_loop типа Option<EventLoop<()>> и метод run, вызывающий self.event_loop.take().unwrap().run(...). К сожалению, мне очень не нравится семантика этого решения, поскольку теоретически цикл событий существует в течение всего срока службы окна, и мое решение, оставляющее None на своем месте, вообще не кажется правильным.

person Christian Ivicevic    schedule 09.05.2021