Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
435 views
in Technique[技术] by (71.8m points)

c++ - gcc 4.7 on linux pthreads - nontrivial thread_local workaround using __thread (no boost)

In C++11 you can have a non-trivial object with thread_local storage:

class X { ... }

void f()
{
    thread_local X x = ...;
    ...
}

Unfortunately this feature hasn't been implemented in gcc yet (as of 4.7).

gcc does allow you to have thread local variables but only with trivial types.

I am looking for a workaround:

Here is what I have so far:

#include <iostream>
#include <type_traits>

using namespace std;

class X
{
public:
    X() { cout << "X::X()" << endl; };
    ~X() { cout << "X::~X()" << endl; }
};

typedef aligned_storage<sizeof(X), alignment_of<X>::value>::type XStorage;

inline void placement_delete_x(X* p) { p->~X(); }

void f()
{
        static __thread bool x_allocated = false;
        static __thread XStorage x_storage;

        if (!x_allocated)
        {
                new (&x_storage) X;
                x_allocated = true;

                // TODO: add thread cleanup that
                //     calls placement_delete_x(&x_storage)
        }

        X& x = *((X*) &x_storage);
}

int main()
{
        f();
}

What I need help with is calling placement_delete_x(&x_storage) on exit of the current thread. Is there a mechanism in pthreads and/or linux I can use to do this? I would need to add a function pointer and a parameter to some sort of pthread cleanup stack?

Update:

I think pthread_cleanup_push might be what I want:

http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cleanup_push.3.html

Will this call the cleanup handler in the correct circumstances for this usage?

Update 2:

It looks like boost::thread_specific_ptr eventually calls pthread_key_create with the destructor parameter, and not pthread_cleanup_push - to call its tls cleanup function:

http://pubs.opengroup.org/onlinepubs/009696799/functions/pthread_key_create.html

It is unclear what the difference between these two methods is, if any. ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

pthread_key_create and friends are what you'd want to implement thread-specific variables of types with destructors. However, these generally require you to manage the whole process of creating and destroying the variables, and I'm not sure whether you could use them in conjunction with __thread.

pthread_cleanup_push is not suitable. It's intended to allow a resource to be released if the thread exits during a (short) block of code that uses that resource; as described in the documentation you link to, it must be matched by a pthread_cleanup_pop at the same level of that function, and the handler won't be called if the thread returns from its main function. That means that you can't use it if you want the thread-local variable to persist between calls to the function.

For the benefit of those who don't have a prohibition against third-party libraries, Boost provides a convenient, portable way to manage thread-local storage.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...