宣言されたファイルスコープ名にstatic
は内部リンクがあります。内部リンケージとは、ダイナミックライブラリのない「クラシック」リンクモデルであっても、他のトランスレーションユニットからは見えないことを意味します。スタティックは、同じ実行可能ファイル内の他の変換ユニットにも表示されないため、接続されているダイナミックライブラリから表示されると期待するのは合理的ではありません。
外部の動的シンボルを使用して必要なリンケージを実現する方法を考える必要があります。おそらく、シングルトンは単に内部名を持つことはできませんが、外部名を持つ必要があります。
Lは、オブジェクトが静的であるという理由だけでなく、そのシングルトンとスレッドプール機能を定義するスレッドプールモジュールをLにリンクしているという理由で、オブジェクトの独自のインスタンスを作成しています。これは、ライブラリがどのようにリンクされているかによっては、外部名を持つオブジェクトでも発生する可能性があります。
スレッドプールサービスが存在する単一のオブジェクトを選択し、それがそこにのみ存在することを確認する必要があります。あなたのプロジェクトには、この種のものに固執できるユーティリティライブラリがありませんか?
スレッドプールAPIを提供するのはプログラム実行可能ファイルPであるというモデルに固執することができます。これは本当に同じことです。プログラムPは別の動的オブジェクトであり、スレッドプールモジュールのライブラリとして効果的に機能し、それ自体と他の共有オブジェクトに提供します。
そのスレッドプールモジュールが存在する場所に関係なく、そのモジュールのコピーを他のオブジェクトに静的にリンクしていないことを確認してください。それは1か所にのみ存在します。
スレッドプールシングルトンの外部名がそのAPIの一部である場合(誰もがその文書化された名前を知っていて、それを直接使用し、そのグローバルプールをAPI関数に渡します)、その名前を外部にし、ヘッダーファイルで宣言する必要があります。
シングルトンをプライベートにする場合は、関数呼び出しで暗黙的にする(スレッドプールが1つしかない)、またはシングルトンへのアクセスをいくらか抽象化するなど、それを隠す方法を考える必要があります(ensure_thread_pool
スレッドプールが存在しない場合はスレッドプールを作成する、またはスレッドセーフな方法で以前に作成したスレッドプールを返す)関数を提供します。
stdin
考えてみてください。たとえば、なぜstdout
この問題が発生しないのでしょうか。stdout
すべてのライブラリが独自のストリームをインスタンス化し、そのストリームで独自のfprintf
関数を呼び出さないのはなぜですか?なぜ、明らかに、これらのものは1つの場所、つまりCライブラリに存在するからです。それらのコピーは他の場所に住んでいません。他の場所では、動的シンボルを介して参照するだけでそれらを使用します。