Programming Microsoft Windows Ce Net 3Rd [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming Microsoft Windows Ce Net 3Rd [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Thread Local Storage

Thread local storage is a mechanism that allows a routine to maintain separate instances of data for each thread calling the routine. This capability might not seem like much, but it has some very handy uses. Take the following thread routine:

int g_nGlobal;            // System global variable
int ThreadProc (pStartData) {
int nValue1;
int nValue2;
while (unblocked) {
//
// Do some work.
//
}
// We're done now; terminate the thread by returning.
return 0;
}

For this example, imagine that multiple threads are created to execute the same routine, ThreadProc. Each thread has its own copy of nValue1 and nValue2 because these are stack-based variables and each thread has its own stack. All threads, though, share the same static variable, g_nGlobal.

Now imagine that the ThreadProc routine calls another routine, WorkerBee. As in

int g_nGlobal;            // System global variable
int ThreadProc (pStartData) {
int nValue1;
int nValue2;
while (unblocked) {
WorkerBee(); // Let someone else do the work.
}
// We're done now; terminate the thread by returning.
return 0;
}
int WorkerBee (void) {
int nLocal1;
static int nLocal2;
//
// Do work here.
//
return nLocal1;
}

Now WorkerBee doesn't have access to any persistent memory that's local to a thread. nLocal1 is persistent only for the life of a single call to WorkerBee. nLocal2 is persistent across calls to WorkerBee but is static and therefore shared among all threads calling WorkerBee. One solution would be to have ThreadProc pass a pointer to a stack-based variable to WorkerBee. This strategy works, but only if you have control over the routines calling WorkerBee. What if you're writing a DLL and you need to have a routine in the DLL maintain a different state for each thread calling the routine? You can't define static variables in the DLL because they would be shared across the different threads. You can't define local variables because they aren't persistent across calls to your routine. The answer is to use thread local storage.

Thread local storage allows a process to have its own cache of values that are guaranteed to be unique for each thread in a process. This cache of values is small because an array must be created for every thread created in the process, but it's large enough if used intelligently. To be specific, the system constant, TLS_MINIMUM_AVAILABLE, is defined to be the number of slots in the TLS array that's available for each process. For Windows CE, like Windows XP, this value is defined as 64. So each process can have 64 4-byte values that are unique for each thread in that process. For the best results, of course, you must manage those 64 slots well.

To reserve one of the TLS slots, a process calls

DWORD TlsAlloc (void);

TlsAlloc looks through the array to find a free slot in the TLS array, marks it as in use, and then returns an index value to the newly assigned slot. If no slots are available, the function returns -1. It's important to understand that the individual threads don't call TlsAlloc. Instead, the process or DLL calls it before creating the threads that will use the TLS slot.

Once a slot has been assigned, each thread can access its unique data in the slot by calling this function:

BOOL TlsSetValue (DWORD dwTlsIndex, LPVOID lpTlsValue);

and

LPVOID TlsGetValue (DWORD dwTlsIndex);

For both of these functions, the TLS index value returned by TlsAlloc specifies the slot that contains the data. Both TlsGetValue and TlsSetValue type the data as a PVOID, but the value can be used for any purpose. The advantage of thinking of the TLS value as a pointer is that a thread can allocate a block of memory on the heap and then keep the pointer to that data in the TLS value. This allows each thread to maintain a block of thread-unique data of almost any size.

One other matter is important to thread local storage. When TlsAlloc reserves a slot, it zeroes the value in that slot for all currently running threads. All new threads are created with their TLS array initialized to 0 as well. This means that a thread can safely assume that the value in its slot will be initialized to 0. This is helpful for determining whether a thread needs to allocate a memory block the first time the routine is called.

When a process no longer needs the TLS slot, it should call this function:

BOOL TlsFree (DWORD dwTlsIndex);

The function is passed the index value of the slot to be freed. The function returns TRUE if successful. This function frees only the TLS slot. If threads have allocated storage in the heap and stored pointers to those blocks in their TLS slots, that storage isn't freed by this function. Threads are responsible for freeing their own memory blocks.

/ 169