Can someone explain Thread.AllocateDataSlot() method?

  • Thread starter Thread starter iam1708 via DotNetMonster.com
  • Start date Start date
I

iam1708 via DotNetMonster.com

I was looking at the docs for Thread and can't understand the different
between "unnamed data slot "and "data slot".and docs in Thread.GetData()
say "Threads use a local store memory mechanism to store thread-specific
data." what is "thread-specific data"?

Best regards
wmt

email:[email protected]
 
iam1708 via DotNetMonster.com said:
I was looking at the docs for Thread and can't understand the different
between "unnamed data slot "and "data slot".and docs in Thread.GetData()
say "Threads use a local store memory mechanism to store thread-specific
data." what is "thread-specific data"?

Best regards
wmt

email:[email protected]

Hi

What you have read about is a Thread Local Storage (TLS). A TLS
variable is a variable that all the threads access in the same way,
but each of the thread can store a different value (each thread has
different copy). TLS makes it easy to write thread safe code. Each
thread has its own stack which means that the variables that declared
on the stack are not shared, but object and class member variables are
shared among all threads. Using TLS you can create non shared
non-stack based variables. In the days of Win32 when I was teaching
the TLS subject I used to give the C strtok() function example: The
function knows how to split a string by tokens. At first you call it
with two arguments, the token string and the start address of the
source string. To get the next word, you call it again, but now you
pass NULL as the address. The function remembers the last address in a
static variable. When you try to split two or more strings with two or
more threads concurrently, you find that all threads work on the same
(last) string. This happens because of the shared nature of the static
variable. Making this variable a TLS solves the problem. Each thread
gets its own copy of the last address state. In .Net there are three
ways to have a TLS:
1) An unnamed TLS, Using Thread.AllocateDataSlot(); the result (slot)
of this method should be shared among all thread. Each thread that
need a private storage uses the Thread.SetData() and Thread.GetData()
passing it the shared slot.
2) A named TLS, Using AllocateNamedDataSlot("Name") to create the
slot. Each thread uses the GetNamedDataSlot() to get the slot and then
the Thread.SetData() and Thread.GetData() to work with the slot.
3) The [ThreadStaticAttribute], on a static variable.

The third option is the easiest one, you just decorate a class
variable and you get a TLS. The second is easier than the first
because you don't have to share a common slot between threads, but you
may collide with other code that uses the same name, so be careful.

If you need a TLS for a single class code, use the
ThreadStaticAttribute. If you need the TLS in many places (many
classes) use one of the Slot based methods. You may also consider the
call context mechanism, if you need the TLS state per call along the
call path.

You may also consider using an object instance per thread which omits
the need of TLS.

Alon Fliess
CTO
The Sela Group
 
Thanks a lot!but I have some question need help.
if the code is bellow ,it's allright.
//static int i;

public __gc class ThreadExample
{
[ThreadStatic]
static int i;

public:
static void ThreadProc()
{
i=0;
while (i<100)
{
printf("%d ,",i);
i++;
}
printf("**\n**");
}
};

int _tmain()
{
Thread *oThread1 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
Thread *oThread2 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
oThread1->Start();
oThread2->Start();
Console::ReadLine();
return 0;
}
===================================
but the code changed as bellow

static int i;

public __gc class ThreadExample
{
//[ThreadStatic]
//static int i;

public:
static void ThreadProc()
{
i=0;
while (i<100)
{
printf("%d ,",i);
i++;
}
printf("**\n**");
}
};

int _tmain()
{
Thread *oThread1 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
Thread *oThread2 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
oThread1->Start();
oThread2->Start();
Console::ReadLine();
return 0;
}

the result is
(First time) "0 ,1 ,2 ,3 ,0 ,2 ,3 ,4 ,5 ,6 ,1 ,8 ,7 ,10 ,11 ,12 ,13 ,14 ,
15 ,16 ,........,99,"
(Second time)"0 ,0 ,1 ,2 ,3 ,......99,"
(Third time) "0 ,1 ,2 ,3 ,1 ,2 ,3 ,0 ,4 ,5 ,....99"
(Fourth time)"0 ,1 ,.....,98 ,99 ,91 "
even "0 ,1 ,2 ,......99 **\n** 0 ,1 ,2 ,.....99"

the result is some strange,because variable "i" is shared.from the result I
think their is anthoer copy of "i" in Cache.and in First time
"0 ,1,2,.....,0,2,......,1,8,7..." ,but before the second "1" output ,"2"
output twice.Why?????

Best regards
wmt
 
iam1708 via DotNetMonster.com said:
Thanks a lot!but I have some question need help.
if the code is bellow ,it's allright.
//static int i;

public __gc class ThreadExample
{
[ThreadStatic]
static int i;

public:
static void ThreadProc()
{
i=0;
while (i<100)
{
printf("%d ,",i);
i++;
}
printf("**\n**");
}
};

int _tmain()
{
Thread *oThread1 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
Thread *oThread2 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
oThread1->Start();
oThread2->Start();
Console::ReadLine();
return 0;
}
===================================
but the code changed as bellow

static int i;

public __gc class ThreadExample
{
//[ThreadStatic]
//static int i;

public:
static void ThreadProc()
{
i=0;
while (i<100)
{
printf("%d ,",i);
i++;
}
printf("**\n**");
}
};

int _tmain()
{
Thread *oThread1 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
Thread *oThread2 = new Thread(new ThreadStart(0,
&ThreadExample::ThreadProc));
oThread1->Start();
oThread2->Start();
Console::ReadLine();
return 0;
}

the result is
(First time) "0 ,1 ,2 ,3 ,0 ,2 ,3 ,4 ,5 ,6 ,1 ,8 ,7 ,10 ,11 ,12 ,13 ,14 ,
15 ,16 ,........,99,"
(Second time)"0 ,0 ,1 ,2 ,3 ,......99,"
(Third time) "0 ,1 ,2 ,3 ,1 ,2 ,3 ,0 ,4 ,5 ,....99"
(Fourth time)"0 ,1 ,.....,98 ,99 ,91 "
even "0 ,1 ,2 ,......99 **\n** 0 ,1 ,2 ,.....99"

the result is some strange,because variable "i" is shared.from the result I
think their is anthoer copy of "i" in Cache.and in First time
"0 ,1,2,.....,0,2,......,1,8,7..." ,but before the second "1" output ,"2"
output twice.Why?????

Best regards
wmt

Hi

There are some potential problems with your test. Counting up to 100
takes less then a time-slice. you should spend some more time in the
loop ( Thread.Sleep() will do, or if you don't want to force context
switch, do some busy wait). If you use global static variable, make it
volatile (the compiler will not optimized it, and this may be the
problem that you see).
Printf uses buffers, it may not print immediate. Are you compiling
with multi-threaded C DLL, You may use System::Console instead printf,
it is thread safe in all cases.

Alon.
 
Thanks!
I instead "Console::write" of "printf" solve this porblem.
 
I have some question need help
method Thread.VolatileWrite() can write a value(example a ariable "i")in
Memory that is visible to all processors in the computer.
my question is:if the Cache of processors refresh immediate(auto) too?
through the example of below ,i believe not.but i can't sure.and if the
Cache of processor not refresh,How to refresh it?

public:
static void ThreadProc()
{
//i=0;
Thread::VolatileWrite(&i, 0);
Console::Write("*, ");
while (i<90)
{
Console::Write(i);
Console::Write(", ");
i++;
}
Console::Write(i);
Console::Write("+, ");
}
};


Best regards
wmt
 
iam1708 via DotNetMonster.com said:
I have some question need help
method Thread.VolatileWrite() can write a value(example a ariable "i")in
Memory that is visible to all processors in the computer.
my question is:if the Cache of processors refresh immediate(auto) too?
through the example of below ,i believe not.but i can't sure.and if the
Cache of processor not refresh,How to refresh it?

public:
static void ThreadProc()
{
//i=0;
Thread::VolatileWrite(&i, 0);
Console::Write("*, ");
while (i<90)
{
Console::Write(i);
Console::Write(", ");
i++;
}
Console::Write(i);
Console::Write("+, ");
}
};


Best regards
wmt

Hi again

Using the VolatileWrite/VolatileRead insure that the CPU refer to the
memory stored value and not a register or cache value (the same as the
volatile keyword). This means that you don't need to flush the CPU
cache to get the real coherent value. Maybe the problem is with your i
variable. Please add the full source code.

Alon.
 
Back
Top