1 puan yazan GN⁺ 2024-07-22 | 1 yorum | WhatsApp'ta paylaş

Pin

  • Pin türü ve pinning kavramı, Rust asenkron ekosisteminin temel yapı taşlarından biridir
  • Ancak Pin, yaklaşılması zor ve yanlış anlaşılmaya açık unsurlardan biridir
  • Bu yazı, Pinin neyi başarmayı amaçladığını, nasıl ortaya çıktığını ve bugün hangi sorunlara sahip olduğunu açıklıyor

Gereksinimler

  • Asenkron fonksiyonlarda referansları desteklemek için Future içinde referansların saklanması gerekiyordu
  • Sorun, bu referansların self-referential olabilmesiydi
  • Örnek kod:
    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
    }
    
  • Barın iç durumu şu şekildedir:
    enum Bar {
        Start { x: i32, y: i32 },
        FirstAwait { z: i32, foo: Foo<'?> },
        Complete,
    }
    
  • Pinin amacı, self-referential türleri güvenli şekilde işleyebilmektir

Çözüm olmayanlar: move constructor’lar ve offset pointer’lar

  • Move constructor’lar ve offset pointer’lar Rust’ta çalışmaz
  • Move constructor’lar taşıma sırasında pointer’ları günceller, ancak bu Rust’ta mümkün değildir
  • Offset pointer’lar ise bir referansın self-referential olup olmadığının derleme zamanında bilinememesi nedeniyle çalışmaz

“Pinned typestate”

  • Bir nesnenin her zaman taşınamaz olması değil, belirli bir andan itibaren taşınamaz olması gerekir
  • Ralf Jung’un modelinde nesne, "owned" durumundan "shared" durumuna ve ardından "pinned" durumuna geçer
  • Pinned duruma girdikten sonra nesne artık taşınamaz

?Move

  • Pinden önce, Move adlı yeni bir trait tabanlı çözüm denenmişti
  • Moveu implement etmeyen türler, referansları alındığında pinned duruma geçiyordu
  • Ancak Move geriye dönük uyumluluk sağlamıyordu

Pin

  • Pin, nesneleri pinned duruma getiren yeni bir referans türü tasarlar
  • Pin, kütüphane API’si olarak uygulanarak geriye dönük uyumluluğu korur
  • Unpin auto trait’i eklenerek çoğu türün pinned durum ile normal durum arasında ayrım yapmasına gerek kalmaz

Pin ile ilgili sorunlar

  • Pin, kullanılabilirlik açısından çeşitli sorunlara sahiptir
  • Pin, kütüphane türü olarak uygulandığı için normal referans türlerinin sahip olduğu birçok özelliği kaybeder
  • Örneğin &mut T, Copy implement etmese de aynı argüman olarak birden fazla kez geçirilebilir
  • Pin bu tür kolaylıkları sağlamaz
  • Pin kullanılırken çok fazla kafa karışıklığı yaşanır

Bir sonraki yazımda…

  • Pin, asenkron fonksiyonlarda keyfi referansların güvenli biçimde derlenebilmesini sağlar
  • Ancak Pin, karmaşıklığı artırır; bunu iyileştirmenin yolları bir sonraki yazıda ele alınacaktır

GN⁺ özeti

  • Pin, Rust asenkron ekosisteminin önemli bir bileşenidir
  • Pinin kullanılabilirlik sorunları, kütüphane türü olarak uygulanmasından kaynaklanır
  • Pini iyileştirme yolları bir sonraki yazıda ele alınacaktır
  • Benzer işlevlere sahip projeler arasında pin-project-lite bulunur

1 yorum

 
GN⁺ 2024-07-22
Hacker News görüşleri
  • Pin'in anlaşılmasının zor olmasının nedeni, resmi belgelerde açık şekilde anlatılmaması

    • Belgeler, "Pin nesnenin asla taşınmamasını garanti eder" iddiasında bulunuyor, ancak bu doğru değil
    • Sıradan nesnelerin çoğu Unpin olduğu için, Pin genellikle hiçbir işe yaramıyor
    • Pin'in gerçekten işe yaradığı T tiplerinin kümesi oldukça sıra dışı ve bu nokta belgelerde yeterince vurgulanmıyor
  • Pin'in zor olmasının nedeni, kendi başına bir anlam taşımaması

    • Pin durumunda, dil ya da standart kütüphane Pin'in ne yapıp ne yapamayacağını söylemiyor
    • Bunun yerine, InnerType sağlayıcısı pinned nesneleri işleyebilmek için ek (içsel olarak güvensiz) metotlar ve API'ler oluşturuyor
    • Pin yapısının tek amacı, daha az "yerleşik işlev" sunan bir işaretçi sağlamak
  • Başlığa "rust" eklenmeli ki yazının ne hakkında olduğu anlaşılsın

  • "value identity" terimi Mojo belgelerinde hiçbir yerde tanımlanmamış

    • Dave Abrahams'ın "Value Semantics: Safety, Independence, Projection, & Future of Programming" konuşması tavsiye ediliyor
  • Pin, teknik olarak doğru ama anlaşılması zor bir adın iyi bir örneği

    • "Drop" daha tanıdık bir anlama sahip, ancak "pinning" öyle değil
    • immovable!(…) daha iyi olabilir, ama daha iyi bir ad bulmak da zor
    • prevent_moving!(…) gibi daha açıklayıcı bir ad ve PreventMove trait'i daha iyi olabilir
  • Rust benzeri bir dilde move-constructor'lar olsaydı Pin'e olan ihtiyaç ortadan kalkabilirdi

    • Kullanıcının nesneyi yok etme yolu olmayacağı için onu taşıma yolu da olmazdı
  • &mut referansı üzerinden mem::swap/replace ile nesneler taşınabiliyor, ancak buna gerçekten ihtiyaç duyulan durumlar nadir

    • Keşke move-reference seçebilmenin bir yolu olsaydı
    • swap ve replace işlemlerini unsafe yapmak sorunu çözebilir
  • WithoutBoats, async iterator'lar, poll ve pin konularında aktif bir tartışma yürütüyor

    • Dilin ayrıntıları hakkında kamuya açık biçimde bu kadar derin tartışan pek az topluluk var ve bunu görmek oldukça ilgi çekici
  • Pinning/!Move, async/await dışında da birçok kullanım için faydalı

    • Ancak Rust bunu düzgün ele alamadığı için, genelde verilen cevap "programı başka bir dilde yeniden yaz" oluyor