13

Haskell ハンドルを使用するとき、少し不安を感じました。つまり、私は 2 つの機能を探しています (既に存在している可能性があります。その場合は、私の無知をお許しください)。

  1. 読み取りと書き込みの両方が可能なハンドル (たとえば、 によって返される) を取得したら、それらを読み取り専用ハンドルと書き込み専用Network.acceptハンドルのペアに変換して、 読み取り専用ハンドルへの書き込みが行われないようにしたいと考えています。型チェックとその逆。(おそらく、ファントム型とラップアラウンド IO 関数を使用してこれを達成できますか?)
  2. 並行設定では、複数のスレッドが同じハンドルに書き込む可能性があることがわかりました。これは、非常に厄介な結果を引き起こします。型システムを介してそれを防ぐにはどうすればよいでしょうか (可能であれば)、少なくとも実行時にスローされた例外を介してそのようなケースの通知を受け取るにはどうすればよいでしょうか?

どんなアイデアでも大歓迎です。

4

2 に答える 2

8

safer -file-handlesライブラリは、あなたが望むことをしているようです。最初の部分はかなり明確に処理されます。同時実行の安全性は、リージョンライブラリRegionTから処理されるようです。私はこれをまったく使用していませんが、かなり一般的なアプローチのようです。

于 2013-08-08T21:26:55.710 に答える
2

ネットワーク コンジットパッケージの使用を検討することをお勧めします。これは、ネットワーク アプリケーションを 2 つの「エンドポイント」が与えられたものとして説明しています。1 つのシンクはデータをソケットにプッシュし、もう 1 つのソースはソケットからデータを読み取ります。

type Application m = AppData m -> m ()

data AppData m Source -- ...
appSource :: AppData m -> Source m ByteStringSource
appSink :: AppData m -> Sink ByteString m ()

これにより、書き込み部分と読み取り部分が明確に分離されます。これで、このようなソースとシンクで好きなことを行うことができます。さらに、それぞれを別のスレッドに渡し、入力と出力を別々に処理することもできます。もちろん、指定したエンドポイントに応じて、それぞれが読み取りまたは書き込みしかできません。

シングルスレッド処理を強制したい場合は、プログラム コンポーネントを として実装するように制限できますConduit ByteString m ByteString。このようなコンジットは、次Applicationのような sに簡単に変換できます。

asApp :: MonadIO m => Conduit ByteString m ByteString -> Application m
asApp cond ad = appSource ad $= cond $$ appSink ad

しかし、コンジットは を使用してデータを要求し、 を使用awaitして出力を書き込むことしかできyieldません。それ以外の場合は、あらゆる種類のハンドルにアクセスできず、エンドポイントをまったく認識しないため、それらをどこにも公開したりリークしたりすることはできません。

于 2013-08-16T12:42:24.523 に答える