[threads] Unexpected behaviour of Thread loal storage

Hello, I would like to ask if there is everything ok with my way of thinking. I have 3 solutions (projects) in MS Visual Studio. Let say: SolutionA (static lib) SolutionB (linked with Solution A) SolutionC (linked with Solution A) In Header file of solutionA I have delaration of TLS from boost static boost::thread_specific_ptr<int> TLS; And now in SolutionB I set tls (TLS.reset(uVariable)) - uVariable is integer 2 Call function from SolutionC and call TLS.get() but there is different value than 2. But when i return from function to SolutionB and call TLS.get there is everything ok (return 2). It's ok ? Why in solutionC there is no visibilty of value set in solutionB ? It's the same thread (with the same threadId). Best regards

On Wed, Apr 29, 2015 at 10:07 AM, Fu ji
Since SolutionA is a static lib, you basically have two different copies of TLS - one in each of the other two solutions that you link with SolutionA. On Windows there is no support for symbol relocation so the two copies continue to be independent after you load SolutionB and SolutionC binaries. Each of these two solutions work with its own copy and not the other. If you want to fix that you have to ensure there is only one instance of the TLS variable. One way to do that is to make SolutionA a shared library (dll).

Thank you for reply, I forget to say that solutionB and solutionC is also dll, so I decided to merge solutionA and SolutionC. Right now I have SolutionB and SolutionC (here is tls) both are dll. The same situation: SolutionB I set tls (TLS.reset(uVariable)) - uVariable is integer 2 Call function from SolutionC and call TLS.get() but there is different value than 2. But when i return from function to SolutionB and call TLS.get there is everything ok (return 2). But still no effect, where I made a mistake ?

Tls is in header in SolutionC. In solutionB there is only header with declaration: class __declspec( dllexport ) TLSslot;

Maybe it's because in solutionB I have delaration of tls (in other way I
have problem with building solution:
file.obj : error LNK2001: unresolved external symbol "public: static class
boost::thread_specific_ptrclassnamespace::CClass
namespace::CThreadLocalStorageSlot::ThreadLocalStorage_"
(?ThreadLocalStorage_@CThreadLocalStorageSlot@tnamespace@
@2V?$thread_specific_ptr@VCThread@namespace@@@boost@@A)
)
2015-04-29 15:18 GMT+02:00 Andrey Semashev

On Wed, Apr 29, 2015 at 4:40 PM, Fu ji
You have to declare the TLS variable in the header, it has to have external linkage. Given that you have two dlls, it must also be exported. For example: // tls.h extern API boost::thread_specific_ptr<int> TLS; Then you have to define this object in one cpp file of SolutionC, like this: // tls.cpp #include "tls.h" API boost::thread_specific_ptr<int> TLS; Here API is a macro which is defined to __declspec(dllexport) when you build SolutionC and __declspec(dllimport) otherwise. PS: This is really not a Boost-related question. You need to understand how linking works on Windows in general.

Thank you for help Andrey but it's still not working. Right now I sipmlify it to minimum, in SolutionC (dll) in Include (tls.h) I have: extern __declspec(dllexport) boost::thread_specific_ptr<int> ThreadLocalStorage; in the same soltuion but in Src i have tls.cpp with: __declspec(dllexport) boost::thread_specific_ptr<int> ThreadLocalStorage; and this is ok, compile with any problems. SolutionB(dll) in file.pp I have: __declspec(dllimport) boost::thread_specific_ptr<int> ThreadLocalStorage; and right now I have a different issue, after compile, run I try to change value of tls in SolutionB in reset funtion I have assertion. Maybe you have some idea why ? Best regards and once again thank you for help.

It was _Block_Type_Is_Valid (pHead->nBlockUse) Error, so I think it was double free and i fix it by all .release before .reset and it helps, but there is the same problem with double instance of tls.

Ok, I already now how weird tree I have in project. First there is run service.exe which load dispather.dll. Here I use function from mainlibrary.dll (there is reference mainlibrary in dispatcher properties). Now from mainlibrary (where is declaration of tls) I load module.dll, in this module I all function from dispather and reset tls with value = 2, back to module and try to get value from tls, but it looks like tls is not initialized with any value. There is a difference beetwen boost tls and tls from win api in this case ?

On Thursday 30 April 2015 14:06:15 Fu ji wrote:
There is a difference beetwen boost tls and tls from win api in this case ?
Boost.Thread TLS is based on the underlying OS API for TLS but it is not compatible. One essential point of difference is that Boost.Thread TLS identifies the pointer by its address (this is why duplicating the pointer breaks your case) while Windows TLS provides a key which can be copied.

I went back to problem, in header I have: extern __declspec(dllexport) boost::thread_specific_ptr<int> Storage; extern __declspec(dllexport) int tls_value_storage = 10; //for test In Src I have: extern __declspec(dllexport) boost::thread_specific_ptr<int> Storage; // Error extern __declspec(dllexport) int tls_value_storage; but here I have error in compiling process, there is ok if there is only declaration without extern (in other case I have error LNK1120: 1 unresolved externalsl). In other project I have: extern __declspec(dllimport) boost::thread_specific_ptr<int> TlxStorage; extern __declspec(dllimport) int tls_value_storage; and it's ok. Integer tls_value_storage is only for testing purpose, it work fine (I can see variable in other project). Thanks in advance.

I try to summing up all things:
I try to export thread local storage (dllexport)
from firstmodule and import in secondmodule (dllimport) but with no effect.
In firstmodule I have Includes/ThreadLocalStorage.h with delaration:
#include

On Wed, May 6, 2015 at 9:37 AM, Fu ji
extern is not needed here, unless you want to define tls_value_storage elsewhere.
Do you link to Boost.Thread built as a shared library (dll)? Both libraries must use Boost.Thread dll because it maintains a global list of thread_specific_ptr storage objects internally.
When you write extern you declare the object which must be defined elsewhere. There must be exactly one definition of the object (without extern), so you would typically declare it in a header (for reuse by other source files) and define in a cpp file. The error says that you provided no definition of the TlsStorage object (because you added the extern keyword, changing the definition into a declaration).

This could be a problem, in both solutions I have in Properties: Additional Include Directories: ..\3rdParty\Common\include\boost (here I have .hpp files) and in Linker: Additional Library Directories: ..\3rdParty\$(Platform)\VC12\lib and here I have libboost_thread-vc120-mt-1_57.lib May I do this in some other way ? I read that I can achieve that by define: #define BOOST_ALL_DYN_LINK in pre-compiled header stdafx.h Thank you for your patience Andrey.

On Wed, May 6, 2015 at 11:25 AM, Fu ji
I don't use Windows but AFAIR the library name should be something like boost_thread-vc120-mt-1_57.lib (note no leading 'lib') and a similarly named dll. If you don't have these you will have to rebuild boost. Make sure you add 'link=shared' to b2 command line.
Yes, BOOST_ALL_DYN_LINK must be defined when you build both your libraries.
participants (2)
-
Andrey Semashev
-
Fu ji