スレッドローカルストレージ(TLS)


http://dozb.bokee.com/3435618.html
スレッドローカルストレージ(TLS)
スレッドローカルストレージ(TLS)は、この方法により、所与のマルチスレッドプロセスの各スレッドに、スレッド特定データを記憶する位置を割り当てることができる方法である.動的バインディング(実行時)のスレッド特定データは、TLS API(TlsAlloc、TlsGetValue、TlsSetValue、TlsFree)方式でサポートされる.既存のAPI実装に加えて、Win 32とVisual C+コンパイラは、現在も静的バインディング(ローディング時間)スレッドベースのデータをサポートしている.
TLSのAPI実現
Win 32 API層とコンパイラによって「スレッドローカルストレージ」が実現される.詳細については、Win 32 APIドキュメントのTlsAlloc、TlsGetValue、TlsSetValue、TlsFreeを参照してください.
Visual C++コンパイラは、API層を介してではなく、スレッドローカルストレージ動作をより自動化するキーを含む.このシンタックスは、次のセクション(TLSのコンパイラ実装)で説明されます.
TLSのコンパイラ実現
TLSをサポートするために、新しい属性threadをCとC+言語に追加しました.Visual C+コンパイラによってサポートされます.この属性は、上記のセクションで説明したように、拡張記憶類の修飾子です.__を使うdeclspecキーワード宣言thread変数.例えば、以下のコードは整数スレッドの局所変数を宣言し、値を用いて初期化する.
__declspec( thread ) int tls_i = 1;

TLS

 

   
   
   
   
  • thread属性は、データ宣言と定義にのみ適用できます.関数宣言や定義には使えません.たとえば、以下のコードはコンパイラエラーを生成します.
    #define Thread  __declspec( thread )
    Thread void func();     // This will generate an error.
  • は、staticスコープを有するデータ項目にのみ、thread修饰子を指定することができる.グローバルデータオブジェクト(staticとexternを含む)、
            C++         。     thread           。            : 
  • を含む.
  • #define Thread  __declspec( thread )
    void func1()
    {
        Thread int tls_i;            // This will generate an error.
    }
    
    int func2( Thread int tls_i )    // This will generate an error.
    {
        return tls_i;
    }
  • スレッドローカルオブジェクトの宣言と定義は、すべてthread属性を指定しなければならない.例えば、以下のコードはエラーを発生します.
    #define Thread  __declspec( thread )
    extern int tls_i;        // This will generate an error, since the
    int Thread tls_i;        // declaration and definition differ.
  • thread属性は、タイプの修飾子として使用できません.たとえば、以下のコードはコンパイラエラーを生成します.
    char __declspec( thread ) *ch;        // Error
  • C++類はthread属性を使用できません.ただし、thread属性を使用してC++クラスのオブジェクトを実例化することができます.例えば、以下のコードは、チューターエラーを生成する.
    #define Thread  __declspec( thread )
    class Thread C       // Error: classes cannot be declared Thread.
    {
    // Code
    };
    C CObject;
    は、thread属性のC+オブジェクトを使用する声明を許可するので、以下の2つの例は意味的に等価である.
  • は、スレッドローカルオブジェクトのアドレスを定数として扱わず、このようなアドレスに関する任意の表現を定数として扱わない.標準Cにおいて、
    #define Thread  __declspec( thread )
    Thread class B
    {
    // Code
    } BObject;               // OK--BObject is declared thread local.
    
    class B
    {
    // Code
    };
    Thread B BObject;        // OK--BObject is declared thread local.
  •                                   。  ,C              : 
    ですが、この制限はC++には適用されません.C+++は全てのオブジェクトを動的に初期化することができるので、スレッドローカル変数アドレスを用いた表式でオブジェクトを初期化することができます.
  • #define Thread  __declspec( thread )
    Thread int tls_i;
    int *p = &tls_i;       //This will generate an error in C.
                                      。  ,           C++             。

    : , 。

  • 標準Cは、自身を参照する表現を含む初期化オブジェクトまたは変数の使用を可能にしているが、非静的な作用領域のオブジェクトにのみ適用されている.
    
       
       
       
       
  •    C++                        ,                     。  : 
    は、初期化されているオブジェクトを含むsizeof式は、自身への参照が確立されておらず、CおよびC+においても合法的であることに注意してください.C+++は、このようなスレッドデータの動的初期化を許可しない.これは、将来、スレッドローカル記憶機能を強化する可能性があるからである.
  • DLLが任意の非ローカルデータまたはオブジェクトを_u u u_uとして宣言する場合declspec(スレッド)は、DLLを動的にロードすると、エラーを保護します.
  •        LoadLibraryを使用してDLLを全部ロードした後、コードが非局所的な__を参照するたびに.declspec(スレッド)データの場合、システムが故障します.スレッドのグローバル変数空間は、実行時に割り当てられているので、この空間の大きさは、アプリケーションの必要性と、すべての静的リンクのDLLの需要を加算して計算される.LoadLibraryを使用すると、この空間を拡張できなくなり、放置用の_udeclspec(スレッド)が宣言するスレッドローカル変数.DLLがLoadLibraryでロードされる可能性がある場合、TLSはDLLでTLS API(TlsAllocなど)を使用して割り当てられてください.