2017/06/18

[linux]通信による衝突はどうやって回避するとよいのかがわからん

昨日の続きだが、わからんシリーズだ。


マルチスレッドで並行に動かしたいわけではないので、終わるまで待たせればいいやん、という結論になった。
今回のプロトコルでは待たせても、処理さえしてくれれば問題ないのだ。

ただ、相手に再送してもらうわけにはいかないので、自分で処理が終わるまで待たせることにした。
mutexではなく、状態変数を持たせ、処理中だったら1秒ごとにチェックして終わったかどうかをループで監視することで待たせることにした。
volatileにしてwhileで回せばいいだろう。


そしたら・・・こういう現象が起きた。

image

あー、そうだね。。。
mutexだろうと状態変数だろうと、待たせるということはそのコンテキストが止まってしまうのだ。
コンテキストを止めたいのではなく、コンテキストで行われる処理を後回しにしたいだけなので、これではダメなのだよ。



じゃあ・・・どうしたらよいのだ?
Cが送信するタイミングではBからデータが来るなんてことはわからない。
だから送信して、このコンテキストはC→B→Aの送信だ、と考える。

しかし、Bからすると先にAから受信しているのでA→B→Cと動くのが自然なので、そういうコンテキストだと考える。
どちらも間違ってはいないのだが、このままではBはCからの受信を待機させるし、CはBからの受信を待機させて、これはこれで流れが止まってしまう。

Aが送信する前にCへ連絡できればよいのだけど、そういうルートはない。
だから、事前に知らせる方法はない。


相手と自分間でどちらかに送信に対する優先度を持たせるとどうだろうか。
幸い、A, B, Cはユニークな識別子を持っていて、その識別子は相手も知っているため、機械的に大小を決めることができる。

  • A>B, B>C : BはCより強いので、Aからの転送を優先させる
  • A<B, B<C : CはBより強いので、Aからの転送は待たせてCの転送を優先させる
  • A<B, B>C : BはCより強いので、Aからの転送を優先させる
  • A>B, B<C : CはBより強いのでB-C間はCの転送を優先させたいが、A-B間はAの方が強いので、Aの転送を優先させたくなる。AとCの強さで決めるしかないか?

最後のパターンでAの方が強かったとしても、CはAを知らないので、「俺はBより強いんだ」と考えてしまうだろう。
データに「あちらのお客様からです」というような情報があれば比較もできるが、それもない。
ダメか・・・。


ここでは一部だけ切り出しているが、実際のプロトコル仕様としてはシーケンスがクロスすることについては規定していないし、クロスしても特に問題はない。
実装の都合でブロックしようと考えただけだ。
もしかすると、ブロックできないことがわかっているから、そういう書き方をしているのかもしれない。

最初はブロックせずに実装していたのだけど、シーケンスとして「お互いの送受信状況を比較する」というようなものがあり、それが相手の転送によって割り込まれると、相手は転送データを受け取っているがこちらはまだ、というタイミングが生じてしまい、比較NGになってしまうのだ。

image


今回のように幅広くブロックするんじゃなくて、比較するぞ、という区間だけ転送を止める方が良いのか。
相手から比較データを送ってくるのは、相手がsendした後だということが決まっているので、相手のsendを受け取ってから比較が終わるまでの間だけ転送をブロックすればよいかもしれん。


いやー、難しい、難しいですよ。。。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。