
Hi, I understand that using tss with the threads library (statically linked, ICL 10.1 on Win32) forces the user to define tss_cleanup_implemented() in the global namespace. Since there is no documentation on this, I would appreciate some information as to whether there are any gotchas: I am assuming that tss_cleanup_implemented() is the place where all thread_specific_ptr's should be reset(). Is there anything else required? Also, are there any special considerations when some of the threads might not have been started through Boost.threads? Btw, thread.hpp is extremely fiddly to use, since it does not define WIN32_LEAN_AND_MEAN, which leads to winsock.h getting included which makes it unuseable with any networking libraries (that use winsock2). I ended up creating my ouwn header that includes this after defning the macro. Thanks a lot Amit

Amit <contact.lipik@gmail.com> writes:
tss_cleanup_implemented() doesn't do anything itself: it is a placeholder. If the library defines it (e.g. for MSVC on Windows, and for POSIX platforms) then thread_specific_ptr values are automatically cleaned up on thread exit. If the library doesn't define it, the user must define it for TSS to work, and the user takes responsibility for ensuring that all TSS variables are correctly cleaned up.
Also, are there any special considerations when some of the threads might not have been started through Boost.threads?
This is the hardest part. For threads launched with Boost.threads, cleanup happens anyway. It is native threads that are tricky.
This is a problem with the date-time headers (which are used by boost threads). I'll see what I can do to get it fixed. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

Amit <contact.lipik@gmail.com> writes:
You need to define BOOST_THREAD_USE_LIB when you build the static library. It should work if you're using MSVC as the backend for ICL.
Apart from this, the library appears to work fine for my use cases (tss, shared & exclusive mutex).
Excellent. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

Anthony Williams <anthony_w.geo <at> yahoo.com> writes:
You need to define BOOST_THREAD_USE_LIB when you build the static library. It should work if you're using MSVC as the backend for ICL.
Thanks, I figured it out. looking at the code (which I should admittedly have done in the first place :) - BOOST_THREAD_BUILD_LIB needs to be defined for tss_pe to be included in the build. I have done the build, but ICL does not like data_seg pragma's in that file; I get 2 types of warnings: a) warning #1026: pragma data_seg should be at global scope b) warning #14: extra text after expected end of preprocessing directive a) is probably because the pragmas are at namespace scope; don't know if this is really a violation or the compiler being fussy. b) this is generated for all data_seg(push, xxx) & data_seg(pop, xxx) pragmas. No idea what the compiler is doing under the hood - documentation does not mention anything about data_seg, and it is not in the list of unsupported pragmas. Will test the code tomorrow & should have more information on the outcome then. But in the worst case, I suppose I can drop tss_pe.cpp from my build and then I become responsible for cleaning up all tss I allocate? Thanks Amit

Amit <contact.lipik@gmail.com> writes:
That's what I meant.
Those are MSVC pragmas. I guess the #ifdefs are wrong.
The TSS tests all pass for ICL with a VC8 backend (see the regression results), so it should be OK (even with the warnings). Yes, if you remove tss_pe.cpp, then you're responsible for TSS cleanup. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

Anthony Williams <anthony_w.geo <at> yahoo.com> writes:
Hi again, The tss seems to be working fine with ICL (though performance falls through the floor if I don't link in their libguide40.dll - but I guess that is an oddity of their implementation). I have a couple of question though. They probably belong on the user list, but since we are discussing the library anyway... a) Is it safe to instantiate thread_specific_ptr as a function level static (i.e. are there likely to be race issues just instantiating the object, in case the first calls of hte function happens to be concurrent?)? I did look through the code this time, it appears to be safe since the call to TlsAlloc is wrapped inside call_once - and it seems to work okay. But given the nature of these things, and my lack of intimate knowledge of SMP, don't know if this is unsound. b) Do you think it is worth providing a wrapper around Interlocked* functions? e.g., I have created the function below for my use, but if POSIX also provides something like the Interlocked* win32 calls, it could be made platform independent if boost.thread provided a CompareExchange wrapper. template<bool yield> inline void AtomicSetWord(volatile long &flag, long setToVal=true, long waitTillVal=false) { while (InterlockedCompareExchange(&flag, setToVal, waitTillVal) != waitTillVal) { if (yield) boost::this_thread::yield(); } } d) And finally, what is the deal with yield? My understanding is that it is not required on pre-emptive multitasking systems (i.e. all modern ones?)? If so, perhaps the documentation is misleading, since it says: "Gives up the remainder of the current thread's time slice, to allow other threads to run." Thanks yet again Amit

Amit <contact.lipik@gmail.com> writes:
thread_specific_ptr is not an aggregate, so use as a function-level static depends on whether or not the compiler supports thread-safe function-level statics. gcc has a switch for this. I don't know about ICL. If this is not safe, the compiler will call the constructor multiple times if multiple threads call the function simultaneously. I recommend having thread_specific_ptr instances at namespace scope, or wrapping them up in a mutex or call_once: void init_my_tss_ptr(boost::thread_specific_ptr<my_class>** p) { static thread_specific_ptr<my_class> tss; *p=&tss; } void foo() { static boost::thread_specific_ptr<my_class>* tss; static boost::once_flag flag=BOOST_ONCE_INIT; boost::call_once(flag,init_my_tss_ptr,&tss); // do stuff with the thread_specific_ptr: // e.g. if(tss->get()) do_stuff(); // or tss->reset(new my_class); }
POSIX doesn't provide atomic ops. However, C++0x will, and I intend to write an implementation of them for boost using platform- or compiler-specific APIs (such as InterlockedXXX on Windows, or gcc atomic built-in functions).
yield() is never /required/, since the OS can pre-empt your thread any time it chooses. However, you can put a call to yield() in what would otherwise be a busy-wait loop in order to allow other threads to proceed rather than consuming CPU time for the current thread looping when there is no progress to be made. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL
participants (2)
-
Amit
-
Anthony Williams