views:

140

answers:

3

Hi,

in this code:

int foo() {
   static int x;
}

is the x global to all threads or local in each thread? Or does that depends on a compiler flag and/or the compiler, so I cannot really know what it is from the code?

Several questions (all of them independent from compiler and compiler flags and OS):

  1. How can I create a static variable which is global to all threads?
  2. How can I create a static variable which is local to each thread?
  3. How can I create a global variable which is global to all threads?
  4. How can I create a global variable which is local to each thread?

I guess that this is not in C++ itself. (Is it in C++0x?) Some Boost lib which can do this?

+1  A: 

Quick partial answers;

(Is it in C++0x?)

Yes. But depends on your compiler's C++0x support too.

Some Boost lib which can do this?

Boost.Threads. See thread local storage therein.

  1. How can I create a static variable which is global to all threads?
  2. How can I create a static variable which is local to each thread?
  3. How can I create a global variable which is global to all threads?
  4. How can I create a global variable which is local to each thread?

Note that typically, static refers to duration and global refers to scope.

C++0x thread constructors are variadic: You can pass any number (and type) of arguments. All of these are available to your std::thread object.

#include <thread>

int main()
{
    int foo = 42;
    std::thread t(foo); // copies foo
    std::thread s(&foo); // pass a pointer
    t.join();
}
dirkgently
+2  A: 

x is global to all threads. Always, independent of compiler and/or its flags. Independent of whether this is in C++1x or C++03. So if you declare a regular global or static local variable, it will be shared between all threads. In C++1x we will have the thread_local keyword. Until then, you can use thread_specific_ptr from Boost.Thread.

usta
To avoid confusion, it's best to refer to the upcoming version as C++0x, even though it wasn't completed before 2010. C++1x is the unofficial name for the version after that, which might be completed before 2020.
Mike Seymour
Hmm, makes sense, though I have seen usages of C++1x meaning to refer to C++10 or C++11. Do you have any links where this naming is discussed, and a consensus is tried to be reached?
usta
@usta: consensus and C++ don't mix well, the next standard was dubbed C++0x and changing its name half-way doesn't really work, especially since Bjarne and some others announced they wanted only 5 years between C++0x and C++1x because industry moves fast, they thus suggested to make less changes next time, so as to keep to the deadline.
Matthieu M.
@usta: As I said, it's unofficial; it's just clearer if you use a name that's always unambiguously meant the next version. Here's a link to Stroustrup's FAQ; the third paragraph gives his opinion, and he also refers to C++1x in one questions: http://www2.research.att.com/~bs/C++0xFAQ.html
Mike Seymour
Thanks for the comments. I'll be sure to follow them to avoid creating confusion, for which I'm sorry I managed to create this time.
usta
A: 

You'd have to be using some kind of cross platform threading library (since you mentioned OS independence), but given pthreads you could do.

template <T>
class myVarStorage
{
    static std::map<int, T> store_;
public:
    myVarStorage();
    T getVar();
    void setVar(T);
}

template <T> void myVarStorage::setVar<T>(T var)
{
     store_[static_cast<int>pthread_self()] = var;
}

template <T> T myVarStorage::getVar()
{
     return store_[static_cast<int>pthread_self()]; //throws exception 
}

I'm sure the code has errors in it and should be treated as pseudo-code, since I'm a pseudo-programmer when it comes to C++. :)

Novikov
Note that your code is not thread-safe, so it needs some additional handling. :) Then, this would be the way to implement it in a safe and crossplatform way. But this is also highly inefficient. You need O(log n) (n being the amount of threads) for each access. In the other solutions, you just need O(1) access time.
Albert
With some pthreads semaphores added the code is still under 20 lines. Code using globals instead of dependency injection is not likely to be fast or well written anyway with or without the overhead of lookups in a tree.
Novikov
To have the variable in the thread stack and to access it is a really fast operation. It is a simple O(1) access and it does not need any locking/unlocking/synchronisation. The latter can have huge affect. It is basically the main reason why you want to have thread-local variables at all.
Albert
Yes, but I fail to see how that can be achieved transparently accross several identical threads without dependency injection or dynamic scoping/compiler support.
Novikov