回答編集履歴

6

誤字を修正しました

2020/03/16 23:03

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -86,7 +86,7 @@
86
86
 
87
87
 
88
88
 
89
- `Mutex`のロックに失敗して`poll_write()`から`Poll::Pending`を返したとします。その後、ロックできる状態になったら、非同期ランタイムから再度`poll_write()`をんでもらわないといけません。そのためには前回の`poll_write()`で引数にとった`Context`内にある`Waker`の`wake()`メソッドを呼ぶことでランタイムに通知する必要があります。
89
+ `Mutex`のロックに失敗して`poll_write()`から`Poll::Pending`を返したとします。その後、ロックできる状態になったら、非同期ランタイムから再度`poll_write()`をんでもらわないといけません。そのためには前回の`poll_write()`で引数にとった`Context`内にある`Waker`の`wake()`メソッドを呼ぶことでランタイムに通知する必要があります。
90
90
 
91
91
 
92
92
 

5

誤字を修正しました

2020/03/16 23:03

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -38,7 +38,7 @@
38
38
 
39
39
  // FutureExtトレイトのboxed()でPin<Box<dyn Future<Output = ..>>に
40
40
 
41
- // 変換し、as_mut()でPin<&mut Future<Output = ..>>に変換すればよい。
41
+ // 変換し、as_mut()でPin<&mut dyn Future<Output = ..>>に変換すればよい。
42
42
 
43
43
  match self.0.lock().boxed().as_mut().poll(cx) {
44
44
 

4

デッドロックに関する説明を訂正しました

2020/03/16 18:25

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -70,7 +70,11 @@
70
70
 
71
71
 
72
72
 
73
- tokioの`Runtime`のようなマルチスレッドな非同期ランタイムでは、非同期タスクに対応していない`Mutex`は使えないようです。[こちら](https://rust-lang.github.io/async-book/03_async_await/01_chapter.html?highlight=mutex#awaiting-on-a-multithreaded-executor) の説明によると、デッドロックを引き起こす恐れがあるそうです。
73
+ ~~tokioの`Runtime`のようなマルチスレッドな非同期ランタイムでは、非同期タスクに対応していない`Mutex`は使えないようです。[こちら](https://rust-lang.github.io/async-book/03_async_await/01_chapter.html?highlight=mutex#awaiting-on-a-multithreaded-executor) の説明によると、デッドロックを引き起こす恐れがあるそうです。~~
74
+
75
+
76
+
77
+ (訂正)参照先の説明をもう一度読んだところ、デッドロックを引き起こす可能性があるのは、複数の`.await`にまたがってロックを使用するときだけだとわかりました。今回の使いかたは、それには該当しないはずです。ただデッドロックは起こらなくても、stdの`Mutex`の`lock()`はブロッキングな操作ですので、非同期タスク内から呼ぶと非同期ランタイムのexecutorスレッドの実行を一時的にブロックします。ですから性能面の影響は多少あるかもしれません。それほど長い時間はブロックしなさそうなので、無視できる範囲かもしれませんが。
74
78
 
75
79
 
76
80
 

3

追記部分の説明を改良しました

2020/03/16 18:23

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -78,7 +78,11 @@
78
78
 
79
79
 
80
80
 
81
- 「追記 2020-03-17 01:20」についてですが、`tokio::sync::Mutex::try_lock()`だとダメそうな気がします。`poll_write()`から`Poll::Pending`を返したあと、ロックできる状態になったら、非同期ランタイムから再度`poll_write()`を読んでもらわないといけません。そのためには前回の`poll_write()`で引数にとった`Context`内にある、`Waker`の`wake()`メソッドを呼ぶことでランタイムに通知する必要があります。
81
+ 「追記 2020-03-17 01:20」についてですが、`tokio::sync::Mutex::try_lock()`だとダメそうな気がします。
82
+
83
+
84
+
85
+ `Mutex`のロックに失敗して`poll_write()`から`Poll::Pending`を返したとします。その後、ロックできる状態になったら、非同期ランタイムから再度`poll_write()`を読んでもらわないといけません。そのためには前回の`poll_write()`で引数にとった`Context`内にある`Waker`の`wake()`メソッドを呼ぶことでランタイムに通知する必要があります。
82
86
 
83
87
 
84
88
 

2

「動かないようでしたら調べますので...」という一文を追加しました。

2020/03/16 17:49

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
 
8
8
 
9
- `poll_write()`の実装を以下のようにしたところコンパイルは通りました。ただし、私は`Future`トレイトや`AsyncWrite`トレイトを実装するのは不慣れですので、これで正しく動くという自信はありません。
9
+ `poll_write()`の実装を以下のようにしたところコンパイルは通りました。ただし、私は`Future`トレイトや`AsyncWrite`トレイトを実装するのは不慣れですので、これで正しく動くという自信はありません。動かないようでしたら調べますので教えてください。
10
10
 
11
11
 
12
12
 

1

質問の「追記 2020-03-17 01:20」にたいする回答を追加しました

2020/03/16 17:44

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -71,3 +71,23 @@
71
71
 
72
72
 
73
73
  tokioの`Runtime`のようなマルチスレッドな非同期ランタイムでは、非同期タスクに対応していない`Mutex`は使えないようです。[こちら](https://rust-lang.github.io/async-book/03_async_await/01_chapter.html?highlight=mutex#awaiting-on-a-multithreaded-executor) の説明によると、デッドロックを引き起こす恐れがあるそうです。
74
+
75
+
76
+
77
+ **追記**
78
+
79
+
80
+
81
+ 「追記 2020-03-17 01:20」についてですが、`tokio::sync::Mutex::try_lock()`だとダメそうな気がします。`poll_write()`から`Poll::Pending`を返したあと、ロックできる状態になったら、非同期ランタイムから再度`poll_write()`を読んでもらわないといけません。そのためには前回の`poll_write()`で引数にとった`Context`内にある、`Waker`の`wake()`メソッドを呼ぶことでランタイムに通知する必要があります。
82
+
83
+
84
+
85
+ 質問の追記部分にあるコードですと、`wake()`メソッドを呼ぶことがないので、ランタイムが`poll_write()`を呼んでくれなくなってしまい、非同期タスクが前に進みません。
86
+
87
+
88
+
89
+ 回答に書いたコードでは`lock()`が返した`Future`の`poll()`で`Context`を引数として渡しています。こうすることで、ロックできる状態になったときに、tokioの`Mutex`の実装側から`wake()`を呼んでもらえます。
90
+
91
+
92
+
93
+ `Waker`の働きについては公式のAsync Bookの [この章](https://rust-lang.github.io/async-book/02_execution/03_wakeups.html) が参考になると思います。