LINEスタンプ制作代行サービス・LINEスタンプの作り方!

お電話でのお問い合わせ:03-6869-8600

stampfactory大百科事典

リエントラント

リエントラント("reentrant"、再入可能)とは、プログラムやサブルーチンが、実行の途中で割り込まれ、その実行が完了する前に再び呼び出され実行されても安全だという性質を指す。割り込みは分岐や呼び出しなどの内部的な動きによって生じる場合もあるし、ハードウェア割り込みやシグナルなどの外部の動きによって生じる場合もある。割り込んでの呼び出しが完了すれば、割り込まれた呼び出しが実行を継続できる。この定義はシングルスレッドのプログラミング環境が起源であり、ハードウェア割り込みで割り込まれた制御の流れが割り込みサービスルーチン (ISR) に転送されることから生まれた。ISRが使用するサブルーチンは割り込みをきっかけとして実行される可能性があるため、リエントラントでなければならない。OSのカーネルが使用するサブルーチンの多くは、カーネルで確保済みのリソースを超えられない制限がありリエントラントではない。そのためISRでできることは限られている。例えば、一般にISRからファイルシステムにはアクセスできないし、場合によってはヒープ領域も確保できない。直接または間接に再帰可能なサブルーチンはリエントラントである。しかし、グローバル変数が処理の流れの中でしか変化しないことを前提としているサブルーチンはリエントラントではない。グローバル変数を更新するサブルーチンが再帰的に呼び出されれば、1回のサブルーチン実行の中でグローバル変数は突然変化することになる。リエントラント性の概念はシングルスレッドの環境に起源があり、マルチスレッド環境でのスレッドセーフという概念とは異なる。リエントラントなサブルーチンはスレッドセーフにすることもできるが、リエントラントだというだけであらゆる状況でスレッドセーフと言えるわけではない。逆にスレッドセーフなコードはリエントラントである必要はない(後述の例を参照)。次の例の codice_1 関数は、リエントラントではない(同時にスレッドセーフでもない)。したがってこれを割り込みサービスルーチン codice_2 で使用すべきでない。codice_1 は codice_4 をスレッド局所記憶にすることでスレッドセーフにできる。しかしそのようにしてもリエントラントにはならず、codice_1 実行中に同じスレッドのコンテキストで codice_2 が呼び出されれば問題を生じる可能性が残っている。次の工夫を加えたswap関数では、実行完了時のグローバルなデータを注意深く一貫性を保つようにしており、完全にリエントラントである。ただし、実行途中のグローバルなデータの一貫性は保証されていないのでスレッドセーフではない。リエントラント性と冪等性は同義ではない。冪等な関数は、何度呼び出したとしても1度だけ呼び出したかのように全く同じ出力を生成する。一般化すれば、共有データを使わず、入力データに基づいて出力データを生成する関数である(ただし、入力や出力はオプション)。共有データはいつでも誰でもアクセスできる。データを誰かが更新し、誰も更新を把握していない場合、そのデータが以前と比べて変化したのかどうかさえ誰にもわからない。冪等性はリエントラント性を包含するが、逆は必ずしも真ではない。データにはスコープという属性がある。グローバルなデータはあらゆる関数のスコープの範囲外にあり、寿命は不定である。一方局所的なデータは関数が呼び出されるたびに生成され、関数から抜けるときに破棄される。局所的データはルーチン間で共有されず、再入時にも共有されない。したがってリエントラント性を阻害しない。グローバルなデータは任意の関数間で共有でき、あるいは再入時にも共有される。したがってリエントラント性を阻害する。リエントラント性はスレッドセーフの概念とは異なるが、密接に関連している。関数がスレッドセーフであっても、リエントラントでないことがある。例えば関数全体をミューテックスで囲むと、マルチスレッド環境では問題を防げるが、割り込みサービスルーチンで使用すると再入時にミューテックスの解放を待ち続けることになる。混乱を避ける鍵は、リエントラントが1つのスレッド実行でも問題になるという点である。リエントラント性はマルチタスクOSの存在する前からの概念である。リエントラントな割り込みハンドラは、割り込み処理中に早期に割り込み可能にする割り込みハンドラである。それによってが低減される。一般に割り込みサービスルーチンをプログラミングする際、割り込みハンドラ内でなるべく早期に割り込み可能な状態にすることが推奨される。それによって割り込みを拾い損なうのを防ぎやすくなる。以下のコードにある関数 codice_7 も codice_8 もリエントラントではない。上記のコードで、codice_7 はグローバル変数 codice_10 に依存している。したがって、2つのプロセス(スレッド)が codice_7 を実行すると、codice_10 に同時並行的にアクセスし、結果はタイミングに依存することになる。したがって、codice_7 はリエントラントではない。その codice_7 を呼び出している codice_8 もリエントラントではない。これらを若干変更したリエントラントである版を以下に示す:新しい版では、グローバル変数 codice_10 は使われていない。引数を渡して、それに基づいて処理を行って結果を返す。共有される可能性のあるオブジェクトにはアクセスしないようになっている。その代わり、呼出し側が前回の戻り値を引数として渡してやらなければならない。このように、リエントラントなサブルーチンでは、必要な静的データは呼出し側が管理しなければならない。次のC言語のコードでは、関数はスレッドセーフだが、リエントラントではない。この codice_17 は複数のスレッドから呼び出されても全く問題はない、しかし、リエントラントな割り込みハンドラがこの関数を呼び出す場合、2つ目の割り込みがこの関数実行中に発生すると、二度目の呼び出しはミューテックスを獲得できず、永久に停止する。割り込みサービスでは他の割り込みをディセーブルするので、システム全体がハングアップすることになる。

出典:wikipedia

LINEスタンプ制作に興味がある場合は、
下記よりスタンプファクトリーのホームページをご覧ください。