How make static variable for across threads?

This is a discussion on How make static variable for across threads? within the C++ Programming forums, part of the General Programming Boards category; I need a static variable that will be initialized only once for all threads. However, when I create a new ...

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    184

    How make static variable for across threads?

    I need a static variable that will be initialized only once for all threads. However, when I create a new thread and check this static variable, it always says it's uninitialized (but asking within the same thread multiple times it says it's already been init's).

    Are static variables (declared outside a class) thread-local?

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,892
    C++ doesn't have a concept of threads, and thus not of thread-local. All variables of static storage duration (globals, function-local statics and class statics) are shared between threads.

    I'm more interesting in how you determine that a variable is uninitialized.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by CornedBee View Post
    C++ doesn't have a concept of threads, and thus not of thread-local. All variables of static storage duration (globals, function-local statics and class statics) are shared between threads.

    I'm more interesting in how you determine that a variable is uninitialized.
    I did:

    Code:
    static long index;
    
    class Test
    {
    public:
          Test()
          {
                 if ( !index ) index =  TlsAlloc();
          }
    };
    How should I be doing it?

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,892
    Sounds reasonable. So it's calling TlsAlloc() again in a new thread? That seems highly unlikely to me.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Unless you have specific reasons to make your variable static OUTSIDE of the class, I'd prefer this:
    Code:
    class Test
    {
    private:
        static long index;
    public:
          Test()
          {
                 if ( !index ) index =  TlsAlloc();
          }
    };
    
    // This should not be in a header-file!
    long Test::index = 0;
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,892
    It occurs to me that, if the class in your case is in a header file, as is the non-class static, you've got undefined behaviour anyway.

    So yeah, definitely make index a class-static variable.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by CornedBee View Post
    It occurs to me that, if the class in your case is in a header file, as is the non-class static, you've got undefined behaviour anyway.

    So yeah, definitely make index a class-static variable.
    I tried that but it's a template class and for some reason it threw an error when I did that. I was calling it inside the templated class like:

    Code:
    MyClass<T>::index
    But it still wouldn't compile. It fails with "undefined reference to 'MyClass<int>::index'" (The int is because that's the version I am creating)
    Last edited by 6tr6tr; 04-22-2008 at 08:13 AM.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by 6tr6tr View Post
    I tried that but it's a template class and for some reason it threw an error when I did that. I was calling it inside the templated class like:

    Code:
    MyClass<T>::index
    But it still wouldn't compile. It fails with "undefined reference to 'MyClass<int>::index'" (The int is because that's the version I am creating)
    Static variables in a templated class can be a bit more tricky.

    Since using TLS is a global type of operation, perhaps a singleton is a more suitable solution to the problem?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by matsp View Post
    Static variables in a templated class can be a bit more tricky.

    Since using TLS is a global type of operation, perhaps a singleton is a more suitable solution to the problem?

    --
    Mats
    OK, I finally got it to compile but I want to be sure I'm doing this properly. Here's the steps:

    1. Declare the class (this is simplified with no error checking)

    Code:
    template <typename T> class Test
    {
         static long index;
    
    public:
         void setIndex();
         T* get();
         ...elided...
    };
    2. Define the static variable and functions
    Code:
    /* 
     * This is what makes it compile BUT only 
     * if I leave out static. So is it defining the
     * proper variable and will it still be static?
     */
    template <typename T> long Test<T>::index;
    
    template <typename T> void Test<T>::setIndex()
    {
         if ( !index ) index = TlsAlloc();
    }
    
    template <typename T> T* Test<T>::get()
    {
         return ( T* ) TlsGetValue( index );
    }

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You don't need static in the defining of the static member, correct. You will, as far as I understand, however, get one index per type T - which may or may not be what you want.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by matsp View Post
    You don't need static in the defining of the static member, correct. You will, as far as I understand, however, get one index per type T - which may or may not be what you want.

    --
    Mats
    Thanks! Yeah, that's exactly what i want. I want there to be one and only one for all threads in which a Test<X> runs but for that to be diff from Test<Y> because I don't want to end up storing the object of type "Y" in the same TLS spot as an object of type "X".

    Thanks again for all the help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Static Local Variable vs. Global Variable
    By arpsmack in forum C Programming
    Replies: 7
    Last Post: 08-21-2008, 03:35 AM
  2. LNK2001 ERROR!!! need help
    By lifeafterdeath in forum C++ Programming
    Replies: 7
    Last Post: 05-27-2008, 05:05 PM
  3. static variable
    By George2 in forum C Programming
    Replies: 2
    Last Post: 08-24-2007, 07:33 AM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM
  5. Static Variable
    By Urmil Vyas in forum C Programming
    Replies: 3
    Last Post: 02-09-2002, 04:10 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21