Can you use thread local variables inside a class or structure
Asked Answered
T

9

31

Like this.

struct some_struct
{
 // Other fields
 .....
 __thread int tl;
}

I'm trying to do that but the compiler is giving me this error.

./cv.h:16:2: error: '__thread' is only allowed on variable declarations
        __thread int tl;
Termination answered 12/6, 2012 at 14:49 Comment(2)
Please post the compiler error you're getting.Charmain
AFAICS __thread is not standard. Which compiler are you using?Endopeptidase
K
25

In C and C++, thread-local storage applies to static variables or to variables with external linkage only.

Local (automatic) variables are usually created on the stack and therefore are specific to the thread that executes the code, but global and static variables are shared among all threads since they reside in the data or BSS segment. TLS provides a mechanism to make those global variables local to the thread and that's what the __thread keyword achieves - it instructs the compiler to create a separate copy of the variable in each thread while lexically it remains a global or static one (e.g., it can be accessed by different functions called within the same thread of execution).

Non-static class members and structure members are placed where the object (class or structure) is allocated - either on the stack if an automatic variable is declared or on the heap if new or malloc() is used. Either way, each thread receives a unique storage location for the variable and __thread is just not applicable in this case, hence the compiler error you get.

Kunming answered 12/6, 2012 at 14:53 Comment(4)
Not with the current meaning of __thread or thread_local but there are quite some situations where it makes sense to have a different member for each thread, wrapped up nicely behind some interface.Iconoclast
I have to disagree -- just because an object is created by a single thread doesn't mean it will be manipulated solely by one thread (e.g. lock-free data structures). Admittedly, this is relatively rare, however.Searching
I would appreciate if any of the downvoters would care to post a contra-example or a better answer or provide suggestions on how to edit the question or edit the question themselves.Kunming
@BeeOnRope I appreciate your comment and have removed the generalisation.Kunming
C
9

gcc imposes the following restrictions on the use of __thread:

The __thread specifier may be applied to any global, file-scoped static, function-scoped static, or static data member of a class. It may not be applied to block-scoped automatic or non-static data member.

The __thread modifier is supported by multiple compiler. It is not inconceivable that the exact restrictions vary somewhat from compiler to compiler.

Cosenza answered 12/6, 2012 at 14:52 Comment(0)
B
6

You should change __thread int tl; to thread_local static int tl;

Belting answered 1/7, 2014 at 2:56 Comment(3)
Then you can't have multiple instances of the struct/class having different values in this field.Uganda
@rustyx: Of course you can have different values in that field: Every thread will have its own value. What you cannot have with standard C++ is a thread_local normal member: Such would have a different value for each object and each thread.Benedic
I don't know, maybe it'd be nice to have different values per thread-class combination.Contemplative
C
5

C11 standard Section 6.7.1 Paragraph 2

At most, one storage-class specifier may be given in the declaration specifiers in a declaration, except that _Thread_local may appear with static or extern.120)

C11 standard Section 6.7.1 Paragraph 3

In the declaration of an object with block scope, if the declaration specifiers include _Thread_local, they shall also include either static or extern. If _Thread_local appears in any declaration of an object, it shall be present in every declaration of that object.

Canale answered 12/6, 2012 at 15:3 Comment(2)
I guess you mean C11, no? C99 didn't have a thread model and all that.Endopeptidase
Corrected. Habit of writing C99.Canale
W
3

According to the old Petzold book 'Programming Windows' (page 1241) you mark a variable as thread local by using the keywords: __declspec (thread). So for instance: __declspec (thread) int iGlobal = 1;

I doubt this could be done in a class though. You can also make the variable static too. [edit] just realized you are probably not running on windows... So I guess for anyone who needs an windows answer, this may be relevant.

Wariness answered 12/6, 2012 at 14:54 Comment(1)
why shouldn't __declspec (thread) work for variables defined in class method ? I'm not being sarcastic, since I notice SOME variables (pointers) defined as just static appear to become corrupted -1 which is puzzlingJudd
M
2

Write this way:

template <class T> struct S {
    thread_local static int tlm;
};
template <> thread_local int S<float>::tlm = 0; // "static" does not appear here

as stated in https://en.cppreference.com/w/cpp/language/storage_duration

Microclimatology answered 14/5, 2019 at 6:18 Comment(0)
Y
1

You can also specify the struct itself as thread local. For example;

#include <pthread.h>

thread_local struct gl_i_t{
    int a; 
    int b;
}GL_i_t;

Then you can use GL_i_t variables inside thread.

Yuu answered 6/12, 2020 at 8:4 Comment(0)
E
0

For C this makes not much sense, static (= global) members are only a feature of C++. And so the new C11 standard (that introduces _Thread_local) doesn't allow it. These beast are allowed basically everywhere were a variable with static storage duration is allowed.

For C++ this could make sense inside a class as analogous to a static member, but if this is allowed by C++11 I have no idea.

Endopeptidase answered 12/6, 2012 at 15:34 Comment(1)
It does not seem allowed, I got C2720 with VS2015: msdn.microsoft.com/en-us/library/w8x1t4f0.aspxBascinet
C
0

You can use thread_local for static members of a class or structure in C++.

struct some_struct
{
 // Other fields
 .....
 thread_local static int tl;
}

This should be fine. So some_struct::tl could have different values in different threads. If you want to define it, you have to add thread_local again:

thread_local int some_struct::tl = 10;
Clyburn answered 29/10, 2020 at 13:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.