Scheme でポートをラッピングするとき

Scheme でポートをラッピングしたときに元のポートへはアクセスさせたくない。 それを実現するには何が必要かを考える。
0
齊藤敦志 @SaitoAtsushi

R6RS にはポートをコピーする機能ないのか。 transcoded-port があるくらいだから内部的にはそういう機能が必要なはずだと思うんだけど。

2015-02-26 04:24:03
Kei @tk_riple

@SaitoAtsushi transcoded-portは受け取ったバイナリポートを閉じるので、実装によってはコピーの必要がないです。

2015-02-26 06:41:40
齊藤敦志 @SaitoAtsushi

@tk_riple 閉じるにもかかわらず状態を引き継ぐのでコピーと表現しました。 ポートをラップするときは元のポートにアクセスして欲しくないことがあるので閉じたいんですけど、そういう方法がないのでどうしたものかなと。

2015-02-26 09:17:33
Kei @tk_riple

@SaitoAtsushi なるほど。実装的な面で考えると、ポートの呼び出しが特定のクロージャ内かどうかを判別しないといけないので、かなり難しいんじゃないかなぁと。

2015-02-26 14:10:15
齊藤敦志 @SaitoAtsushi

@tk_riple そうですか? ポートの複製をとってから元のポートを無効 (クローズ) にできればいいだけだと思うのですが。

2015-02-26 14:49:14
Kei @tk_riple

@SaitoAtsushi あぁ、そうか。そうですね。擬似クローズでなんとかできないか考えてました。

2015-02-26 15:03:30
Kei @tk_riple

そうは言っても、カスタムポートに対してポートのコピーをどうするのかというのはやはり難しい気がする。特にクローズが捕捉したポートも閉じる場合とか。

2015-02-26 15:05:25
Shiro Kawai @anohana

@tk_riple ポートのコピー、ってここでは内容を入力から出力に流すことじゃなくてインスタンスの複製ってこと?

2015-02-26 15:07:08
Kei @tk_riple

@anohana はい。なのでr6rsのカスタムポートの複製はかなり難しいかなぁと。

2015-02-26 15:10:39
Kei @tk_riple

内容を全部input/outputポートに流し込んで、要らない側を閉じればとも思ったが、コピー元が出力ポートだと詰むな。思った以上に厄介な問題なのかもしれない。

2015-02-26 15:15:43
齊藤敦志 @SaitoAtsushi

ポートをファイルハンドルとみなせば、全てのハンドルをクローズしたときに実体もクローズされるようにすれば充分なんじゃなかろうか。 (参照カウント方式)

2015-02-26 15:16:44
齊藤敦志 @SaitoAtsushi

あればすごく便利だけど、無ければ無いなりでなんとかできるので割に合わない気もしてきた

2015-02-26 15:18:39
Shiro Kawai @anohana

@tk_riple 一般的なセマンティクスを決められる気がしないのでそもそもなぜそれをしたいと思ったか気になる…生のポートだってどこまでの外部リソースが共有されるかで曖昧性ができるだろうし。

2015-02-26 15:19:58
齊藤敦志 @SaitoAtsushi

.@anohana @tk_riple バイナリポートをテキストポートに切り替える transcoded-port は元となるバイナリポートを閉じたりするんですが、それを一般化してポートをラップしたときに元のポートを閉じれないかというのが元です。

2015-02-26 15:26:54
Shiro Kawai @anohana

@SaitoAtsushi @tk_riple ああなるほど。元のバイナリポートを閉じる意図はリソースに対するシングルコピー(複数箇所からアクセスしないようにする)なわけだけど、元がカスタムポートだと困るって話かな。とするとクローズとは別の「他からアクセスさせない仕組み」が要るか

2015-02-26 15:38:55
Kei @tk_riple

@anohana @SaitoAtsushi この「他からアクセスさせない仕組み」の上手い案がないんですよね。ポートが環境を知るくらいしかなさそうな気がしてるのですが。

2015-02-26 15:44:53
齊藤敦志 @SaitoAtsushi

@anohana @tk_riple ポートを複製してから閉じるんじゃなくて C++ のムーブセマンティクスみたいに元ポートの情報をもった新しいポートを作ると同時に元のポートを無効にしてしまうという「移動」が出来れば充分に用を成すと思ったのですがどうでしょう。

2015-02-26 15:45:26
Shiro Kawai @anohana

@SaitoAtsushi @tk_riple ですね。実装上は一段間接参照かまして、本体への新たな間接参照を作成&オリジナルの間接参照を無効にする、でいけると思いますが、汎用的な仕様にするのはちとめんどうかも。

2015-02-26 15:48:58
Kei @tk_riple

この場合、共有リソースのことまで考える必要があるのかは疑問ではあるのだが。コピーして元のポートは閉じるってユースケースだと問題になりそう。

2015-02-26 15:57:09
Shiro Kawai @anohana

@tk_riple @SaitoAtsushi 所有権の移動とポートのクローズは全く別にすべきですね。で、ムーブ後の元ポートをクローズしたらどうなるかだけど、call-with系でリソース開放を確実にしたいとすれば、無効間接参照でもクローズだけは効く方がいいかなあ。

2015-02-26 16:03:38
Kei @tk_riple

@anohana @SaitoAtsushi それだと元々の「他からアクセスさせない仕組み」が構築できないような。コピー&クローズで実装だとクローズの際にリソースが閉じてしまうのでは?

2015-02-26 16:09:34
Kei @tk_riple

@anohana @SaitoAtsushi あ、違うか、所有権の移動は別でやれば回避できるのか。

2015-02-26 16:10:35
Shiro Kawai @anohana

@tk_riple @SaitoAtsushi はい、所有権の移動は間接参照でやるってことにして、無効フラグが立った間接参照ではクローズ以外の操作はエラーにする。クローズについては元の参照でも新しい参照でもok。重複クローズok。

2015-02-26 16:12:02
Kei @tk_riple

@anohana @SaitoAtsushi moveだから所有権はコピー側に移るのか。確かにそれならいけそうな気がしますね。

2015-02-26 16:19:16