Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A szál helyi tárolása (TLS) az a módszer, amellyel egy adott többszálas folyamat egyes szálai lefoglalhatják a szálspecifikus adatok tárolására szolgáló helyeket. A dinamikusan kötött (futásidejű) szálspecifikus adatokat a TLS API (TlsAlloc) támogatja. A Win32 és a Microsoft C++ fordító mostantól támogatja a statikusan kötött (betöltési idő) szálonkénti adatokat a meglévő API-implementáció mellett.
Compiler implementáció a TLS-hez
C++11: A thread_local tárosztály-meghatározó az objektumok és osztálytagok szálalapú tárolásának ajánlott módja. További információ: Storage-osztályok (C++).
Az MSVC egy Microsoft-specifikus attribútumot, szálat is biztosít kiterjesztett tárosztály-módosítóként.
__declspec A kulcsszóval deklarálhat egy változótthread. Az alábbi kód például egy egész szál helyi változóját deklarálja, és inicializálja egy értékkel:
__declspec( thread ) int tls_i = 1;
Szabályok és korlátozások
A statikusan kötött szál helyi objektumainak és változóinak deklarálásakor az alábbi irányelveket kell betartani. Ezek az irányelvek mind a szálra , mind a thread_local vonatkoznak:
Az
threadattribútum csak osztály- és adatdeklarációkra és definíciókra alkalmazható. Függvénydeklarációkhoz vagy definíciókhoz nem használható. A következő kód például fordítóhibát okoz:__declspec( thread )void func(); // This will generate an error.A
threadmódosító csak astatickiterjedéssel rendelkező adatelemeken adható meg. Ide tartoznak a globális adatobjektumok (staticésextern), a helyi statikus objektumok, és a C++ osztályok statikus adattagjai. Az automatikus adatobjektumok nem deklarálhatók azthreadattribútummal. A következő kód fordítási hibákat generál:void func1() { __declspec( thread )int tls_i; // This will generate an error. } int func2(__declspec( thread )int tls_i ) // This will generate an error. { return tls_i; }A deklarációknak és a szál helyi objektumának definíciójának mind meg kell adnia az
threadattribútumot. A következő kód például hibát okoz:#define Thread __declspec( thread ) extern int tls_i; // This will generate an error, since the int __declspec( thread )tls_i; // declaration and definition differ.Az
threadattribútum nem használható típusmódosítóként. A következő kód például fordítóhibát okoz:char __declspec( thread ) *ch; // ErrorMivel az attribútumot használó
threadC++ objektumok deklarációja engedélyezett, a következő két példa szemantikailag egyenértékű:__declspec( thread ) class B { // Code } BObject; // OK--BObject is declared thread local. class B { // Code }; __declspec( thread ) B BObject; // OK--BObject is declared thread local.A szál helyi objektumának címe nem tekinthető állandónak, és az ilyen címeket tartalmazó kifejezések nem tekinthetők állandó kifejezésnek. A C szabványban az a célja, hogy ne engedélyezze egy szál-lokális változó címének használatát objektum vagy mutató inicializálójaként. A C fordító például a következő kódot jelöli hibaként:
__declspec( thread ) int tls_i; int *p = &tls_i; //This will generate an error in C.Ez a korlátozás a C++-ban nem érvényes. Mivel a C++ lehetővé teszi az összes objektum dinamikus inicializálását, inicializálhat egy objektumot egy olyan kifejezéssel, amely egy szál helyi változójának címét használja. Ugyanúgy történik, mint a szál helyi objektumainak felépítése. A korábban bemutatott kód például nem okoz hibát, ha C++ forrásfájlként van lefordítva. A szál helyi változójának címe csak addig érvényes, amíg a címmel rendelkező szál továbbra is létezik.
A Standard C lehetővé teszi egy objektum vagy változó inicializálását egy olyan kifejezéssel, amely önmagára mutató hivatkozást tartalmaz, de csak nemsztatikus méretű objektumok esetében. Bár a C++ általában lehetővé teszi az objektumok ilyen dinamikus inicializálását olyan kifejezéssel, amely magában foglalja a magára való hivatkozást, az ilyen típusú inicializálás nem engedélyezett a szál helyi objektumaival. Például:
__declspec( thread )int tls_i = tls_i; // Error in C and C++ int j = j; // OK in C++, error in C __declspec( thread )int tls_i = sizeof( tls_i ) // Legal in C and C++Az
sizeofinicializálandó objektumot tartalmazó kifejezés nem önmagára mutató hivatkozást jelent, és c és C++ nyelven is engedélyezve van.A C++ nem teszi lehetővé a száladatok ilyen dinamikus inicializálását a szál helyi tároló létesítményének lehetséges jövőbeli fejlesztései miatt.
A Windows Vista
__declspec( thread )előtti Windows operációs rendszereken bizonyos korlátozások vonatkoznak. Ha egy DLL bármilyen adatot vagy objektumot__declspec( thread )deklarál, az védelmi hibát okozhat, ha dinamikusan betöltődik. Miután a DLL betöltődött a LoadLibraryval, rendszerhibát okoz, amikor a kód az__declspec( thread )adatokra hivatkozik. Mivel a szál globális változóterülete futásidőben van lefoglalva, ennek a térnek a mérete az alkalmazás követelményeinek és a statikusan csatolt DLL-ek követelményeinek kiszámításán alapul. Ha használja aLoadLibrary, nem tudja kiterjeszteni ezt a területet, hogy lehetővé tegye a__declspec( thread )-el deklarált szál helyi változókat. A TLS API-kat, például a TlsAlloc-t, használja a DLL-ben a TLS foglalásához, ha a DLL betölthetőLoadLibrary.