Rustの std::sync::RwLock はLinuxでwriter starvation問題を起こす (macOSなら平気)

お腹が減ったワンちゃん

まとめ:

  • std::sync::RwLock::{write(), try_read()} を併用した場合には「書き込みロックを最優先」という挙動は必ずしも期待できない (LinuxではNG)
  • Pthread の規約が挙動に自由度をもたせており、Linuxにおけるデフォルト実装では writer starvation が発生する
  • Rustにおいて writer starvation を回避しつつ readers-writer lock を使うには parking_lot::RwLock を使うと良い

続きを読む


Rustでmockするならmockallで決まり!・・・でよろしいでしょうか?

Rustで DI (Dependency Injection)、してますか?
今日話題にするのはドメイン層でインターフェイスを定義してインフラ層でその実装を書くやつです。
例えばドメイン層で trait UserRepository を書いて、インフラ層で struct UserRepositoryImpl するやつです。

テストを書くとき、 struct UserRepositoryImpl はDBアクセスなどしてしまうので取り回しが悪いから、mock を作って fixture を入出力したいことありますよね。
Rustでそういうことやるなら mockall がオススメだよという記事です。

そんなに不満はないのですが、もしベターなやり方があったら記事末尾のコメントやTwitterやらもらえたら嬉しいです。

前職のFOLIO時代の同僚で現CADDiの むらみんさんの記事

外部通信のような比較的大きい副作用が絡むテストに於いて テストダブルを差し込むことは可能なのですが、かなりの労力が必要になる印象を持っています。

と書いていたのを今更ながら発見して、自分はこうしてるけど皆はどうしてるんだろ?と思って筆(キーボード)を取りました。

続きを読む


Rustの2種類の 'static

2種類の 'static

Rustの 'static 、難しいですよね。

「プログラム中ずっと生き残るライフタイムでしょ?簡単簡単」

なるほど。では次の2つの 'static の違いがわかるでしょうか?

1つめ
1
let x: &'static str = "Hello, world.";
2つめ
1
2
3
/// Returns some reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { ... }

「・・・2つめのなんだっけ?」
という人はぜひ読んでみてください🦀

この記事では、Rustの2種類の 'static

  • 'static ライフタイム
  • 'static ライフタイム 境界

を解説します。

続きを読む


ぼくのかんがえたさいきょうの CircleCI 設定 for Rust

あまり見ない気がするので書きました。特徴は、

  • lint, testなどの各ジョブが並列に動く(ジョブ実行数を多くしてないとdocker containerの立ち上げ分むしろ全体時間はロスになることもあるが…)。
  • Travis CI のマトリクスビルド に近いことを、 parameters: を使ってやっている。
    • rust-toolchain ファイル に書かれたバージョンと、 .circleci/config.yml に書かれた MSRV (Minimum Supported Rust Version) の2つでビルドしている。
  • cargo-readme を使ってrustdocとREADMEを比較し、どちらかがメンテされていない場合にエラーにする(お好みで)。
  • キャッシュ使う。

あたりです。見慣れなさそうなところはインラインコメント付けましたので参考にしてください 💁‍♀️

続きを読む


二分探索木 - Rustではじめるデータ構造とアルゴリズム(第2回)

簡単な二分探索木

Rustの特徴のひとつは、所有権(ownership)・移動(move)・借用(borrow)の概念です。これらがコンパイル時に厳格にチェックされることにより、古くから未定義挙動でプログラマを悩ませてきたダングリングポインタなどの問題がなくなり、メモリ安全性がもたらされます。

しかし一方で、自分で多少複雑なデータ構造を定義しようとする場合にはコンパイルを通すだけでもかなりの知識・力量が要求されます。

この(不定期)連載では、 Rustではじめるデータ構造とアルゴリズム と題し、プログラミングコンテストなどでよく見かける基礎的なデータ構造とアルゴリズムを、できるだけシンプルにRustで実装していきます。 &, &mut, Box, Rc, Cell, RefCell などの使い分けや、なぜそれを使う必要があるかの解説を、実例を通して行います。

今回第2回では、 二分探索木 を取り扱います。値の大小に沿った構造を持つ二分木であり、単純なデータ構造でありながら、検索やソートなど実用性が高いです。第1回の二分木に少し制約を付け足した構造になるので、未読の方はぜひ第1回のほうからご覧ください。

続きを読む


二分木 - Rustではじめるデータ構造とアルゴリズム(第1回)

簡単な二分木(引用元: Wikipedia)

Rustの特徴のひとつは、所有権(ownership)・移動(move)・借用(borrow)の概念です。これらがコンパイル時に厳格にチェックされることにより、古くから未定義挙動でプログラマを悩ませてきたダングリングポインタなどの問題がなくなり、メモリ安全性がもたらされます。

しかし一方で、自分で多少複雑なデータ構造を定義しようとする場合にはコンパイルを通すだけでもかなりの知識・力量が要求されます。

この(不定期)連載では、 Rustではじめるデータ構造とアルゴリズム と題し、プログラミングコンテストなどでよく見かける基礎的なデータ構造とアルゴリズムを、できるだけシンプルにRustで実装していきます。 &, &mut, Box, Rc, Cell, RefCell などの使い分けや、なぜそれを使う必要があるかの解説を、実例を通して行います。

第1回は、最もシンプルな木構造である 二分木 を取り扱います。基礎的な木構造なので、再帰・深さ優先探索・幅優先探索のエッセンスを集中的に理解することが期待できます。

各回共通し、以下のような構成を予定しています。

  1. データ構造の説明と、Rustでの定義
  2. 関連するアルゴリズムの説明と、(汎用的に実装できる場合は)Rustでの実装
  3. 定義したデータ構造とアルゴリズムを使って、プログラミングコンテストの問題を解いてみる

続きを読む