Cách nào tốt hơn để xử lý các lần đóng trong WebAssugging với Rust thay vì sử dụng bộ nhớ quên và rò rỉ?


8

Khi cung cấp các cuộc gọi lại cho JavaScript bằng cách sử dụng Closures , cách nào tốt hơn để giải quyết việc tránh giải phóng chúng? Các hướng dẫn wasm-bindgen gợi ý sử dụng .forget, nhưng thừa nhận rằng đó là về cơ bản bị rò rỉ bộ nhớ.

Thông thường chúng tôi sẽ lưu trữ tay cầm để sau đó bị bỏ rơi vào một thời điểm thích hợp nhưng hiện tại chúng tôi muốn nó là một trình xử lý toàn cầu vì vậy chúng tôi sử dụng forgetphương pháp để thả nó mà không làm mất hiệu lực đóng cửa. Lưu ý rằng đây là bộ nhớ bị rò rỉ trong Rust, vì vậy điều này nên được thực hiện một cách thận trọng!

Nó gợi ý về việc lưu trữ các bao đóng cho đến khi nó thích hợp để được thả. Trong câu trả lời của alexcrichton cho một câu hỏi trước đó , anh ta đề cập đến ...

[...] nếu nó [...] chỉ được gọi một lần, thì bạn có thể sử dụng Rc/ RefCellđể thả Closurebên trong bao đóng (sử dụng một số shenanigans biến đổi bên trong)

Nhưng anh ta không cung cấp một ví dụ về phương pháp này.

Các tài liệu Đóng cửa cũng đưa ra một ví dụ về trả lại tham chiếu đến việc đóng cửa với bối cảnh hoạt Javascript để cho nó xử lý khi để giải phóng tài liệu tham khảo.

Nếu chúng ta thả cbở đây, nó sẽ gây ra một ngoại lệ bất cứ khi nào khoảng thời gian trôi qua. Thay vào đó, chúng tôi trả lại tay cầm của chúng tôi trở lại JS để JS có thể quyết định khi nào hủy khoảng thời gian và phân bổ việc đóng cửa.

Tôi cũng tưởng tượng có nhiều cách để sử dụng các tính năng như thời gian sống hoặc #[wasm_bindgen]macro trên một chức năng công cộng để tránh vấn đề này, nhưng tôi gặp khó khăn khi tìm ra cách thực hiện theo cách đó.

Câu hỏi của tôi là, các lựa chọn thay thế nào để sử dụng .forgetvới các bao đóng được chuyển lại cho JavaScript từ Rust và tôi có thể xem một số ví dụ đơn giản về mỗi tùy chọn đang sử dụng không?

Câu trả lời:


1

Gần đây tôi đã xây dựng một ứng dụng thương mại nhỏ và bị mắc kẹt trong vài tuần và thực sự phấn khích khi tôi làm việc này. Tôi đã kết thúc bằng cách sử dụng Clos.once_into_js . Tuy nhiên, điều đó cũng có một lời cảnh báo rằng "Cách duy nhất FnOnce được giải quyết là bằng cách gọi hàm JavaScript. Nếu hàm JavaScript không bao giờ được gọi thì FnOnce và mọi thứ nó đóng sẽ bị rò rỉ." Vì vậy, nếu cuộc gọi lại được gọi, mọi thứ sẽ ổn, nhưng nếu không, vẫn còn rò rỉ bộ nhớ. Tôi thấy phong cách lập trình là khá đẹp. Tôi đã ánh xạ các hàm JavaScript thành Rust như thế này:

#[wasm_bindgen]
fn getSomething(details: &JsValue, callback: JsValue);

pub fn get_something(details: &Details, callback: impl Fn(Option<String>) + 'static){
    getSomething(&serde_wasm_bindgen::to_value(details).unwrap(), Closure::once_into_js(move |v: JsValue| 
        callback(serde_wasm_bindgen::from_value(v).unwrap())   
    ));
}

Và sau đó tôi có thể sử dụng nó từ Rust trong ứng dụng của mình như vậy:

let callback = move |id| {
};
get_something(&details, callback);

Tôi đã định nghĩa các cuộc gọi lại là các hàm impl tĩnh và sau đó di chuyển các giá trị vào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.