ソフトウェアエンジニアリングでは、パイプラインは、各要素の出力が次の要素の入力となるように配置された処理要素(プロセス、スレッド、コルーチン、関数など)の連鎖で構成されます。この概念は、物理的なパイプラインに類似しています。通常、連続する要素間には、ある程度のバッファリングが提供されます。これらのパイプラインを流れる情報は、多くの場合、レコード、バイト、またはビットのストリームであり、パイプラインの要素はフィルタと呼ばれることがあります。これは、モノリシックなパイプとフィルタの設計パターンとも呼ばれます。その利点は、シンプルさと低コストですが、欠点は、弾力性、耐障害性、スケーラビリティの欠如です。[ 1 ]要素をパイプラインに接続することは、関数合成に類似しています。
厳密に言えば、パイプラインは線形かつ一方向ですが、この用語はより一般的な流れにも適用されることがあります。例えば、主に一方向のパイプラインでも、レクサーハックのように、リターンチャネルまたはバックチャネルと呼ばれる逆方向の通信が行われる場合があり、また、パイプラインが完全に双方向である場合もあります。一方向ツリーや有向非巡回グラフトポロジーを持つ流れは、線形パイプラインと同様の動作をします。このような流れにはサイクルがないため単純であり、そのため、大まかに「パイプライン」と呼ばれることがあります。
パイプラインは、マルチタスクOSにおいて、すべての要素をプロセスと同時に起動し、各プロセスからのデータ読み取り要求を上流プロセスによって書き込まれたデータで自動的に処理することで実装されることが多い。これはマルチプロセスパイプラインと呼ばれる。このようにして、スケジューラはCPUのアイドル時間を最小限に抑えるように、プロセス間でCPUを自然に切り替えることができる。その他の一般的なモデルでは、プロセスに伴うOSのオーバーヘッドを削減するために、要素は軽量スレッドまたはコルーチンとして実装される。OSによっては、スレッドはOSによって直接スケジューリングされる場合もあれば、スレッドマネージャによってスケジューリングされる場合もある。コルーチンは常に何らかのコルーチンマネージャによってスケジューリングされる。
読み取りおよび書き込み要求は通常、ブロッキング操作です。これは、書き込み時にソースプロセスの実行が、宛先プロセスにすべてのデータが書き込まれるまで中断されることを意味します。同様に、読み取り時に宛先プロセスの実行が、ソースプロセスから要求されたデータの少なくとも一部が取得されるまで中断されます。これは、両方のプロセスが互いの応答を無期限に待ち続けるデッドロックにはつながりません。なぜなら、少なくとも一方のプロセスはすぐにオペレーティングシステムによって要求が処理され、実行を継続するからです。
パフォーマンス向上のため、パイプを実装するほとんどのオペレーティングシステムではパイプバッファを使用します。これにより、ソースプロセスは、宛先プロセスが現在受信できる、または受信しようとしているデータよりも多くのデータを提供できます。ほとんどのUnixおよびUnixライクなオペレーティングシステムでは、通常「buffer」と呼ばれる特別なコマンドも利用可能で、これは、潜在的に非常に大きく、構成可能なサイズのパイプバッファを実装します。このコマンドは、宛先プロセスがソースプロセスよりも著しく遅いが、ソースプロセスがタスクをできるだけ早く完了したい場合に役立ちます。たとえば、ソースプロセスがCDからオーディオトラックを読み取るコマンドで構成され、宛先プロセスが波形オーディオデータをMP3などの形式に圧縮するコマンドで構成されている場合です。この場合、トラック全体をパイプバッファにバッファリングすることで、CDドライブの回転速度を速め、エンコード処理が完了する前にユーザーがドライブからCDを取り出すことができます。
このようなバッファコマンドは、データの読み書きを行うシステムコールを使用して実装できます。ポーリングやセレクト、マルチスレッドなどの機能を使用することで、無駄なビジーウェイトを回避できます。
パイプラインソフトウェアシステムの代表的な例としては、以下のようなものがあります。
CMS Pipelinesは、パイプラインの概念をVM/CMSおよびz/OSシステムに移植したものです。Unixシェルよりもはるかに複雑なパイプライン構造をサポートしており、複数の入力ストリームを受け取り、複数の出力ストリームを生成するステップに対応しています。(このような機能はUnixカーネルでサポートされていますが、構文が複雑になり、ブロッキングモードが発生するため、使用するプログラムは少ないです。ただし、一部のシェルでは任意のファイルディスクリプタ割り当てによってサポートされています。)
IBMメインフレームオペレーティングシステム上の従来のアプリケーションプログラムには、リダイレクトやパイプ処理を可能にする標準の入出力ストリームがありません。CMS Pipelinesは、外部プログラムでプロセスを生成する代わりに、軽量ディスパッチャを備えており、一般的なUNIXユーティリティを実装し、デバイスやオペレーティングシステムサービスと連携する200以上の組み込みプログラムのインスタンスを並行して実行します。組み込みプログラムに加えて、CMS Pipelinesは、入出力ストリームを持つユーザー作成のREXXプログラムをパイプラインで使用できるフレームワークも定義しています。
IBMメインフレーム上のデータは通常、レコード指向ファイルシステムに格納され、接続されたI/Oデバイスはストリームモードではなくレコードモードで動作します。そのため、CMS Pipelines内のデータもレコードモードで処理されます。テキストファイルの場合、1レコードには1行のテキストが格納されます。一般的に、CMS Pipelinesはデータをバッファリングせず、レコード単位でデータをプログラム間で同期的に渡します。これにより、相互接続されたパイプラインネットワーク全体を通して、データの確実な流れが保証されます。
バイトストリームベースのパイプラインの他に、オブジェクトパイプラインも存在します。オブジェクトパイプラインでは、処理要素はテキストではなくオブジェクトを出力します。PowerShellには、PowerShellランタイム内の関数間で.NETオブジェクトを転送する内部オブジェクトパイプラインが含まれています。Limboプログラミング言語のチャネルも、このメタファーの例です。
RISC OSやROX Desktopなどのグラフィカル環境もパイプラインを使用しています。RISC OSとROXでは、プログラムがデータを書き込む場所をユーザーが指定できるようにファイルマネージャを含む保存ダイアログボックスを提供する代わりに、アイコン(および名前を指定するフィールド)を含む保存ダイアログボックスを提供します。保存先は、アイコンをドラッグアンドドロップすることで指定します。ユーザーは、既に保存済みのファイルがドロップできる場所であればどこにでもアイコンをドロップできます。他のプログラムのアイコンにドロップした場合、そのアイコンがロードされ、本来保存されるはずだった内容が新しいプログラムの標準入力ストリームに渡されます。
例えば、インターネットを閲覧しているユーザーが、編集して再アップロードしたい.gz形式の圧縮画像を見つけたとします。GUIパイプラインを使用すれば、リンクを解凍プログラムにドラッグし、抽出されたコンテンツを表すアイコンを画像エディタにドラッグして編集し、「名前を付けて保存」ダイアログを開き、そのアイコンをアップロードソフトウェアにドラッグすることができます。
概念的には、この方法は従来の保存ダイアログボックスでも使用できるが、そのためにはユーザーのプログラムがファイルシステム内で明確かつ容易にアクセスできる場所に配置されている必要がある。しかし、実際にはそうでない場合が多いため、GUIパイプラインは稀である。
「パイプライン」という名前は、物理的な配管と大まかに類似しており、パイプラインは通常[ 2 ]、水がパイプの中を流れるように、情報が一方向にのみ流れることを可能にする。
パイプとフィルタは、バイトストリームをデータオブジェクトとして使用する関数型プログラミングの一形態と見なすことができます。より具体的には、 I/O用の特定のモナドの形態と見なすことができます。[ 3 ]
パイプラインの概念は、Cocoonウェブ開発フレームワークや、XProc(W3C標準)の実装においても中心的な役割を果たしており、ソースストリームを最終的な表示前に変更することを可能にする。
このパターンは、プログラムの入出力としてテキストストリームを使用することを推奨しています。テキストプログラム用のグラフィックシェルを作成する際には、このテキストへの依存を考慮に入れる必要があります。