1 điểm bởi GN⁺ 2024-07-22 | 1 bình luận | Chia sẻ qua WhatsApp

Pin

  • Kiểu Pin và khái niệm pinning là những thành phần nền tảng của hệ sinh thái bất đồng bộ trong Rust
  • Tuy nhiên, Pin là một trong những yếu tố khó tiếp cận và dễ bị hiểu sai
  • Bài viết này giải thích Pin muốn đạt được điều gì, nó hình thành như thế nào, và những vấn đề hiện tại của Pin là gì

Requirements

  • Để hỗ trợ tham chiếu trong hàm bất đồng bộ, cần phải lưu tham chiếu bên trong Future
  • Vấn đề là các tham chiếu này có thể là tự tham chiếu
  • Mã ví dụ:
    async fn foo<'a>(z: &'a mut i32) { ... }
    async fn bar(x: i32, y: i32) -> i32 {
        let mut z = x + y;
        foo(&mut z).await;
        z
    }
    
  • Trạng thái nội bộ của Bar như sau:
    enum Bar {
        Start { x: i32, y: i32 },
        FirstAwait { z: i32, foo: Foo<'?> },
        Complete,
    }
    
  • Mục tiêu của Pin là thao tác với các kiểu tự tham chiếu một cách an toàn

Non-solutions: move constructors and offset pointers

  • Constructor di chuyển và con trỏ offset không hoạt động trong Rust
  • Constructor di chuyển sẽ sửa con trỏ khi di chuyển, nhưng điều đó là không thể trong Rust
  • Con trỏ offset không hoạt động vì tại thời điểm biên dịch không thể biết một tham chiếu có phải là tự tham chiếu hay không

The “pinned typestate”

  • Đối tượng không phải là luôn luôn không thể di chuyển, mà phải trở nên không thể di chuyển từ một thời điểm nhất định
  • Trong mô hình của Ralf Jung, đối tượng chuyển từ trạng thái "được sở hữu" sang trạng thái "được chia sẻ", rồi sang trạng thái "được cố định"
  • Khi đã vào trạng thái cố định, đối tượng không thể di chuyển nữa

?Move

  • Trước Pin, đã có nỗ lực thử một giải pháp dựa trên trait mới tên là Move
  • Kiểu không triển khai Move sẽ chuyển sang trạng thái cố định khi lấy tham chiếu
  • Tuy nhiên, Move không cung cấp khả năng tương thích ngược

Pin

  • Pin thiết kế một kiểu tham chiếu mới để đưa đối tượng vào trạng thái cố định
  • Pin được triển khai như một API thư viện nên vẫn giữ được tính tương thích ngược
  • Bằng cách thêm auto trait Unpin, phần lớn các kiểu không cần phân biệt giữa trạng thái cố định và trạng thái thông thường

The problems with Pin

  • Pin có nhiều vấn đề về mặt tính dễ sử dụng
  • Pin được triển khai như một kiểu thư viện, nhiều tính năng vốn có của kiểu tham chiếu thông thường đã bị mất đi
  • Ví dụ, &mut T không triển khai Copy nhưng vẫn có thể được truyền làm đối số nhiều lần
  • Pin không cung cấp sự tiện lợi này
  • Rất nhiều nhầm lẫn phát sinh khi sử dụng Pin

In my next post…

  • Pin giúp các hàm bất đồng bộ có thể được biên dịch an toàn với các tham chiếu tùy ý
  • Tuy nhiên, Pin làm tăng độ phức tạp, và bài viết tiếp theo sẽ bàn về cách cải thiện điều này

Tóm tắt của GN⁺

  • Pin là một thành phần quan trọng của hệ sinh thái bất đồng bộ Rust
  • Vấn đề về tính dễ sử dụng của Pin xuất phát từ việc nó được triển khai như một kiểu thư viện
  • Bài viết tiếp theo sẽ bàn về các cách cải thiện Pin
  • Một dự án có chức năng tương tự là pin-project-lite

1 bình luận

 
GN⁺ 2024-07-22
Ý kiến Hacker News
  • Lý do Pin khó hiểu là vì tài liệu chính thức không giải thích rõ ràng

    • Tài liệu nói rằng "Pin đảm bảo đối tượng tuyệt đối không bị di chuyển", nhưng thực tế không phải vậy
    • Hầu hết các đối tượng thông thường đều là Unpin, nên Pin thường không có tác dụng gì
    • Tập hợp các kiểu TPin thực sự có tác dụng là rất đặc biệt và tài liệu không nhấn mạnh đủ điều này
  • Pin khó là vì bản thân nó không có ý nghĩa gì riêng

    • Với Pin, ngôn ngữ hay thư viện chuẩn không cho biết Pin có thể và không thể làm gì
    • Thay vào đó, bên cung cấp InnerType sẽ tạo thêm các phương thức và API bổ sung (không an toàn ở mức nội bộ) để có thể thao tác với đối tượng đã được pin
    • Mục đích duy nhất của chính Pin là cung cấp một con trỏ có ít "chức năng nội tại" hơn
  • Nên thêm "rust" vào tiêu đề thì mới biết bài viết nói về gì

  • Thuật ngữ "value identity" không được định nghĩa ở bất kỳ đâu trong tài liệu của Mojo

    • Khuyến nghị bài nói "Value Semantics: Safety, Independence, Projection, & Future of Programming" của Dave Abrahams
  • Pin là một ví dụ điển hình về cái tên chính xác về mặt kỹ thuật nhưng khó hiểu

    • Drop mang nghĩa quen thuộc hơn, còn "pinning" thì không như vậy
    • Có thể immovable!(…) sẽ tốt hơn, nhưng cũng khó nghĩ ra tên nào hay hơn
    • Những tên mô tả như prevent_moving!(…) cùng với trait PreventMove có thể sẽ tốt hơn
  • Nếu một ngôn ngữ tương tự Rust có move-constructor thì nhu cầu với Pin có thể biến mất

    • Vì người dùng không có cách nào để phá hủy đối tượng, nên cũng sẽ không có cách nào để di chuyển nó
  • Có thể di chuyển đối tượng qua tham chiếu &mut bằng mem::swap/replace, nhưng trên thực tế hiếm khi thật sự cần

    • Sẽ tốt hơn nếu có cách để chọn tham chiếu-di chuyển
    • Biến swapreplace thành không an toàn có thể giải quyết được vấn đề
  • WithoutBoats đang có các cuộc thảo luận rất sôi nổi về chủ đề async iterator, poll, pin

    • Gần như không có cộng đồng nào công khai thảo luận sâu về các chi tiết của ngôn ngữ, và điều này rất thú vị để theo dõi
  • Pinning/!Move hữu ích cho nhiều mục đích ngoài async/await

    • Nhưng vì Rust xử lý việc này chưa tốt, nên câu trả lời thường thấy là "hãy viết lại chương trình bằng ngôn ngữ khác"