質問
単純なプログラミング言語のインタープリターを開発しています。
- ツリー構造の動的データがあります。各データノードには、関連付けられた(所有されている)タイプオブジェクトがあります。
- ListType、StructTypeなどのタイプと、特別な TypeRef のタイプがあります。 TypeRefは、具体的な型を参照する名前(文字列)を保持しています。
- (ほぼ)グローバルマップ(辞書)があります-私はそれを environment と呼びます-(
std::map<string, Type*>
)型名を型オブジェクトに変換します。
問題は、いくつかのプログラムがロードされている可能性があり、それぞれが同じ名前に関連付けられた異なるタイプを持つ可能性があることです。この単一の前提により、1つのグローバル(静的)環境を持つことは不可能になります。そうしないと、完璧なソリューションになります。
したがって、(#1)各タイプオブジェクトの環境へのポインター、または(#2)環境のコンテキストですべての操作を実行する必要があるようです(たとえば、どこでも最初の引数として提供することにより) )。
見た問題:
(#1)接続されたすべてのデータノードが同じ環境を持つため、情報の冗長性。環境は、厳密に分離されたデータに対してのみ異なります。
(#2)環境をサブルーチンに簡単に渡し、コードを難読化します。
この問題は、私が ほぼ静的なデータ と呼ぶ一般的なパターンと一致するように思えます。最適なソリューションは何ですか?
解決 3
スレッドローカルストレージを使用するというアイデアは興味深いものですが、最終的には別の解決策になりました。
2つのフェーズで型を使用します。最初はすべて作成され、次に<!> quot; compiled <!> quot;です。コンパイルには環境が必要ですが、一度だけ実行されます。それは、すべてのタイプ名を適切なタイプオブジェクトに変換することにあります。コンパイル後、環境は不要になります。
それでも、一般的な解決策よりも回避策の方が多いと思います。
他のヒント
環境を分けるものは何ですか?実行コンテキスト(コンテキスト内のオブジェクトが同じコンテキスト内のオブジェクトのみを呼び出す)の場合、環境ごとに1つのスレッドを使用して<!> quot; local-globals <!> quotを保存できます。スレッドローカルストレージ(または、キーがスレッドIDであるグローバルマップのみ)。
これにはいくつかの欠点があります。たとえば、クロスコンテキスト呼び出しがある場合は機能しません。そしてもちろん、それはあなたをスレッドモデルに強制します。
2つの型ストレージが必要な場合があります。1つは具象型のグローバル、もう1つはTypeRefのローカルです。ローカルストレージは、現在解析中のプログラムのコンテキストに配置する必要があります。