Code:void testTLS() { ...elided... Test* t; if ( !( t = ( Test* ) TlsGetValue( index ) ) { t = new Test(); TlsSetValue( index, t ); } ...elided... //This cause the error delete t; //If I remove this, it works properly }
Code:void testTLS() { ...elided... Test* t; if ( !( t = ( Test* ) TlsGetValue( index ) ) { t = new Test(); TlsSetValue( index, t ); } ...elided... //This cause the error delete t; //If I remove this, it works properly }
What kind of error?
Post the smallest piece of compilable code that exhibits the problem. It's hard to tell when you've elided parts of the code.
Perhaps because the logic path taken did not include the call to "new".
Mainframe assembler programmer by trade. C coder when I can.
The "send this to microsoft" is simply a response to an access violation. If you call the function you posted [assuming it's not got any "funny" stuff in the ... elided ... sections], you will delete t every time you enter the function. I'm pretty sure you should not delete this element until you have decided to not use the TLS element (remember, TLS only stores a pointer to your object, so if you delete it in the midst of using TLS, it will "disappear" before you've finished with it.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
>> if ( !( t = ( Test* ) TlsGetValue( index ) )
Don't type up psuedo-code of what you think the code is doing - copy/paste - remove anything you think doesn't apply. But even then, you may remove the code that's cuasing the problem.
Write up a very simple console app that demonstrates the problem. Post that so others can compile and debug if need be.
gg
I'm in a kind mood today, so I'm posting some TLS code that works:
--Code:#include <iostream> #include <sstream> #include <process.h> #include <windows.h> volatile int threadCount = 0; int index = -1; typedef int TLSData; TLSData *getTls(void) { return (TLSData *)TlsGetValue(index); } TLSData *makeTls(int content) { TLSData *p = new TLSData; *p = content; TlsSetValue(index, p); return p; } void destroyTls(void) { TLSData *p = getTls(); delete p; } void threadfunc(void *ap) { int threadId = *(int *)ap; TLSData *t; for(int i = 0; i < 100; i++) { std::stringstream ss; if ((t = getTls()) == NULL) t = makeTls(threadId); ss << "Thread " << *t << std::endl; std::cout << ss.str(); Sleep(500); } destroyTls(); threadCount--; } int main() { index = TlsAlloc(); if (index == TLS_OUT_OF_INDEXES) { std::cout << "Error, out of TLS indexes" << std::endl; return 1; } for(int i = 0; i < 6; i++) { _beginthread(threadfunc, 0, &i); threadCount++; Sleep(1500); } while(threadCount > 0) Sleep(1000); TlsFree(index); return 0; }
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
(nasty v-keyword)
Some minor improvements to matsp code
ggCode:#include <iostream> #include <sstream> #include <process.h> #include <windows.h> #if _MSC_VER >= 1400 volatile int threadCount = 0; #else #error "Compiler not supported" #endif int index = -1; typedef int TLSData; TLSData *getTls() { return (TLSData *)TlsGetValue(index); } TLSData *makeTls(int content) { TLSData *p = new TLSData; *p = content; TlsSetValue(index, p); return p; } void destroyTls() { TLSData *p = getTls(); delete p; } void threadfunc(void *ap) { int threadId = (int)ap; TLSData *t; for(int i = 0; i < 5; i++) { std::stringstream ss; if ((t = getTls()) == NULL) t = makeTls(threadId); ss << "Thread " << *t << std::endl; std::cout << ss.str(); Sleep(500); } destroyTls(); threadCount--; } int main() { index = TlsAlloc(); if (index == TLS_OUT_OF_INDEXES) { std::cout << "Error, out of TLS indexes" << std::endl; return 1; } for(int i = 0; i < 6; i++) { _beginthread(threadfunc, 0, (void*)i); threadCount++; //Sleep(1500); } while(threadCount > 0) Sleep(1000); TlsFree(index); return 0; }
So, I presume volatile is no longer supported by the new compiler because it always makes globals volatile??? (Or is that version 1.4, not version 14 - my compiler certainly accepts the code, and it's using VC 7.0)
The sleep 1500 in main is to make the subsequent threads start later - otherwise it's hard to tell which thread is actually running when - it obviously serves no purpose to anything else.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
>> I presume volatile is no longer supported ...
I think you're looking at it backwards...
Microsoft added multi-threaded semantics to volatile starting at version 14.0.0 (VC++ 2005). The "semantics" being "interlocked-style" access to volatile variables. Using volatile in this fashion on any other compiler is incorrect.Code:#if _MSC_VER >= 1400 volatile int threadCount = 0; #else #error "Compiler not supported" #endif
http://cboard.cprogramming.com/showt...687#post701687
>> it obviously serves no purpose to anything else
Since you're passing the address of i, I assumed the sleep was to allow enough time for the thread to dereference it. It's not a good way to communicate i to the threads.
gg
Ok, but the way that the variables are used in the code I wrote is sufficiently simple that reloading them will work. But I'm sure there are better ways to know if all the threads have finished - I just didn't want to spend the time searching for those ways - I don't do Windows thread programming every day... The purpose of my code was to show how to use TLS, and as far as I can see, you haven't changed that.
That is indeed a good point, although it was not actually my intention.>> it obviously serves no purpose to anything else
Since you're passing the address of i, I assumed the sleep was to allow enough time for the thread to dereference it. It's not a good way to communicate i to the threads.
gg
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.