[cfe-dev] __thread keyword (was Re: status of 'thread_local')

James Gregurich bayoubengal at me.com
Thu Oct 18 18:33:23 PDT 2012


Tim,

sorry. I just re-read your message and realized that I confirmed what you already said. I didn't correctly understand what you were telling me on the first pass.


So, I suppose the answer to my original question is that this feature is a work-in-progress and I should stick with boost::thread_specific_ptr for now.

-James


On Oct 18, 2012, at 4:09 PM, James Gregurich <bayoubengal at me.com> wrote:

> 
> On Oct 16, 2012, at 2:29 PM, James Gregurich <bayoubengal at me.com> wrote:
> 
>> ok. I'll test it and see.
>> 
>> 
>> On Oct 16, 2012, at 2:26 PM, Tim Northover <t.p.northover at gmail.com> wrote:
>> 
>>>> What is the lifetime on a __thread variable?  It gets destructed at the time
>>>> the thread exits?
>>> 
>>> Pretty much. From C++11 (3.7.2):
>>> 
>>> "All variables declared with the thread_local keyword have thread
>>> storage duration. The storage for these
>>> entities shall last for the duration of the thread in which they are
>>> created. There is a distinct object or
>>> reference per thread, and use of the declared name refers to the
>>> entity associated with the current thread."
>>> 
>>> "A variable with thread storage duration shall be initialized before
>>> its first odr-use (3.2) and, if constructed,
>>> shall be destroyed on thread exit."
>>> 
>>> I wouldn't swear to LLVM implementing these semantics yet though. The
>>> initial TLS specification forbade non-trivial constructors and had no
>>> mention of destructors. In fact, from a quick test it looks like LLVM
>>> destroys the object at program exit, and only in one thread (unless
>>> __cxa_atexit and to a lesser extent .init_array are more magical than
>>> I knew).
>>> 
>>> Tim.
>> 
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
> 
> 
> 
> ok. I ran the test with '__thread'. I did not get the expected results.
> 
> When I ran the code below, I got one instance of 'a' created on thread 2 which was later released on the main thread by cxa_exit().
> 
> If I moved 'x' to be a global variable (file scope), I still got one instance constructed by cxx_global_var_init() before main was invoked.
> 
> I verified that I am getting multiple worker threads during the running of this app. So, I would expect each worker thread to get a copy of 'x'. 
> 
> 
> Is my expectation wrong? Is this feature not fully implemented or is there some option that needs to be enabled?
> 
> 
> I tested building against the 10.7 & 10.8 SDKs.  Xcode 4.5.1 with clang & libc++ in c++11 mode.
> 
> 
> 
> #include <thread>
> #include <mutex>
> #include <memory>
> #include <sstream>
> #include <iostream>
> #include <vector>
> #include <Foundation/Foundation.h>
> 
> #include <dispatch/dispatch.h>
> 
> 
> 
> class a
> {
> 
> public:
>     a(size_t theLoopId) : mLoopId(theLoopId)
>     {
>         std::thread::id tmpCurrentThreadId = std::this_thread::get_id();
>         std::hash<std::thread::id> tmpThreadHasher;
>         mThreadId = tmpThreadHasher(tmpCurrentThreadId);
>         
>         NSLog(@"construct. thread=%zX, loop=%zX", mThreadId, mLoopId);
>     }
>     
> 
> 
> 
>     ~a()
>     {
>         NSLog(@"destruct. thread=%zX, loop=%zX", mThreadId, mLoopId);
>     }
> 
> 
> 
>     size_t mThreadId;
>     size_t mLoopId;
>     size_t counter;
> };
> 
> template <typename tpType>
> struct drop_pointer
> {
>     
> };
> 
> 
> template <typename tpType>
> struct drop_pointer<tpType*>
> {
>     typedef tpType type;
> };
> 
> struct deleteDispatchgroup
> {
>     void operator()(dispatch_group_t thePtr)
>     {
>         //not needed if ARC is enabled on 10.8+
>         #if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080 || !__has_feature(objc_arc)
>         dispatch_release(thePtr);
>         #endif
>     };
> };
> 
> //__thread  a  x(-1);
> 
> int main(int argc, const char * argv[])
> {
>     dispatch_queue_t tmpDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
>     std::unique_ptr< drop_pointer<dispatch_group_t>::type, deleteDispatchgroup > tmpDipatchGroupSPtr( dispatch_group_create() );
> 
>     size_t tmpCounter = 0;
>     
>     for(size_t i = 1; i <= 50; ++i)
>     {
> 
>         auto tmpHandler = [&tmpCounter, i](void) // (size_t theId)
>         {
>             static __thread a  x(i);
>             
>             for(size_t j= 0; j < 10000000; ++j)
>             {
> 
>                 tmpCounter += j * i;
>                 x.counter += j * i;
>             }
>             
>         };
>         
>         dispatch_group_async(tmpDipatchGroupSPtr.get(), tmpDispatchQueue, tmpHandler);
>     }
>     
>     
>     dispatch_group_wait(tmpDipatchGroupSPtr.get(), DISPATCH_TIME_FOREVER);
> 
> 
>     // insert code here...
>     std::cout << "Hello, World!\n";
>     return tmpCounter;
> }
> 
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20121018/80733d2a/attachment.html>


More information about the cfe-dev mailing list