質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

2回答

1752閲覧

AsRef<Path> の thread::spawn move の方法

yukimemi

総合スコア11

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2019/04/30 05:54

前提・実現したいこと

rust で AsRef<Path> の値を thread spawn で move したい。

発生している問題・エラーメッセージ

rust

1error[E0277]: `P` cannot be sent between threads safely 2 --> src/main.rs:56:5 3 | 456 | thread::spawn(move || { 5 | ^^^^^^^^^^^^^ `P` cannot be sent between threads safely 6 | 7 = help: within `[closure@src/main.rs:56:19: 65:6 path:P, tx:std::sync::mpsc::Sender<walkdir::DirEntry>]`, the trait `std::marker::Send` is not implemented for `P` 8 = help: consider adding a `where P: std::marker::Send` bound 9 = note: required because it appears within the type `[closure@src/main.rs:56:19: 65:6 path:P, tx:std::sync::mpsc::Sender<walkdir::DirEntry>]` 10 = note: required by `std::thread::spawn`

該当のソースコード

fn get_entries<P: AsRef<Path>>(path: P) -> mpsc::Receiver<DirEntry> { let (tx, rx) = mpsc::channel::<DirEntry>(); thread::spawn(move || { let _ = WalkDir::new(path) .into_iter() .map(|e| match e { Ok(e) => tx.send(e).unwrap(), Err(e) => eprintln!("{}", e), }) .collect::<Vec<_>>(); drop(tx); }); rx }

path なので、文字列ではなく、 AsRef<Path> として渡したいと思っています。
rust だとこういう場合どういう風にやるのがいいのでしょうか?

thread への渡し方、後は rsut 流だとこうする、みたいなのもあれば教えて欲しいです。

rust バージョン

2018

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

自分なら以下のようにメソッド内でPathBufに変換します。

rust

1use std::sync::mpsc; 2use std::thread; 3use std::path::Path; 4 5use walkdir::{DirEntry, WalkDir}; 6 7fn get_entries<P: AsRef<Path>>(path: P) -> mpsc::Receiver<DirEntry> { 8 let path = path.as_ref().to_path_buf(); 9 let (tx, rx) = mpsc::channel::<DirEntry>(); 10 thread::spawn(move || { 11 let _ = WalkDir::new(path) 12 .into_iter() 13 .map(|e| match e { 14 Ok(e) => tx.send(e).unwrap(), 15 Err(e) => eprintln!("{}", e), 16 }) 17 .collect::<Vec<_>>(); 18 drop(tx); 19 }); 20 rx 21}

理由として、スレッドやタスク間で値を送り合うときはownedな形式にしてしまったほうが良い (どうせspawnやsendのコストがかかる) と考えています。

別解として、以下のように P: Send + 'static を課してもコンパイルが通ります

rust

1use std::sync::mpsc; 2use std::thread; 3use std::path::Path; 4 5use walkdir::{DirEntry, WalkDir}; 6 7fn get_entries<P: AsRef<Path> + Send + 'static>(path: P) -> mpsc::Receiver<DirEntry> { 8 let (tx, rx) = mpsc::channel::<DirEntry>(); 9 thread::spawn(move || { 10 let _ = WalkDir::new(path) 11 .into_iter() 12 .map(|e| match e { 13 Ok(e) => tx.send(e).unwrap(), 14 Err(e) => eprintln!("{}", e), 15 }) 16 .collect::<Vec<_>>(); 17 drop(tx); 18 }); 19 rx 20}

しかし実際のところ、実用上は P = PathBufP = String くらいしか使い道がなくなってしまうと思います。それだと AsRef<Path> とおく意味があまりなく、 Into<PathBuf> でもよさそうだと思いました。

投稿2019/04/30 06:42

qnighy

総合スコア210

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

素早い回答ありがとうございます!2通りのパターンどちらもすごく参考になりました!

投稿2019/04/30 09:12

yukimemi

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問