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

James Gregurich bayoubengal at me.com
Thu Oct 18 16:09:46 PDT 2012


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;
}

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


More information about the cfe-dev mailing list