3

I was recently using an object whose purpose is to allocate and deallocate memory as a singleton. Something like

class MyValue { // ... static Allocator& GetAllocator() { static Allocator allocator; return allocator; } // ... }; 

I realized later Allocator is not thread-safe: when multiple threads were using the same allocator concurrently, occasionally strange things were happening, causing assertions and segmentation faults.

Solution: use different allocators for different threads:

class MyValue { // ... static Allocator& GetAllocator() { thread_local static Allocator allocator; return allocator; } // ... }; 

Awesome! My problems are gone! Just one question: Will my allocator variable be initialized every time a thread is created, even if the majority of threads won't use this variable?

The initialization of the allocator might be heavy operation, so I would like it to be initialized only when it is actually required, not in every thread.

I read that thread_local variables are allocated by each thread. Does that mean they are also constructed? And does this allocation (or construction) happen systematically for each thread that is created or just for threads that use it?

I faintly remember hearing in a course that most details about threads and thread-local storage are platform dependent. If this is the case, I'm particularly interested in Linux and FreeBSD.


Related (interesting reads, but I could not find the answer there):

9
  • 2
    Are you sure you should have static Allocator GetAllocator() instead of static Allocator& GetAllocator()? The singleton pattern is the latter Commented Apr 13, 2018 at 14:57
  • Also, What does the thread_local mean in C++11? seems to answer your question: Something that is thread-local is brought into existence at thread creation and disposed of when the thread stops. i.e., constructed and destructed Commented Apr 13, 2018 at 14:59
  • preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11 Commented Apr 13, 2018 at 15:11
  • Possible duplicate of What is dynamic initialization of object in c++? Commented Apr 13, 2018 at 15:23
  • @NathanOliver: good point. Right, it returns an l-value reference. I will correct this in the question. Commented Apr 13, 2018 at 15:34

2 Answers 2

7

[basic.stc.thread] states

  1. 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.

  2. A variable with thread storage duration shall be initialized before its first odr-use (6.2) and, if constructed, shall be destroyed on thread exit.

So, you will get storage for the object in each thread. We also have [stmt.dcl]/4 that states

Dynamic initialization of a block-scope variable with static storage duration (6.7.1) or thread storage duration (6.7.2) is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization.

So, if we reach the declaration then the object will be initialized and if it has a constructor, it will be called.

If we put that all together you will have a number of constructor and destructor calls equal to the number of threads that actually reach

thread_local static Allocator allocator; 
Sign up to request clarification or add additional context in comments.

3 Comments

You mean a thread local variable, even if not used in a thread, the storage will always be allocated, but won't be initialized (constructor)?
@BaiyanHuang With my understanding of how everything works, yes. I can't find anything in the standard to say if this has to be the case but I believe all implementations allocate space on the stack for all local variables, regardless if they are initialized or not.
yea, standard tends to say this leaves to implementations, I wrote an example by which I could see the constructor is called only in thread where the thread local get used, but not sure if the storage is pre-allocated for all thread or just allocated before calling the constructor only in those thread that referenced it
1

I can give you a solution to check whether it creates a new object of type Allocator each time you call GetAllocator(). Just call this method at least 5 times and check the address of all the object return. If address of all the return object are different then yes its creates different object in each call or if not it just return the address of same object each time you call GetAllocator().

1 Comment

The empirical approach you propose is clear, but I would like to understand the theory. I have enough experience to no longer blindly trust the result of simple experiments as a way to uncover the truth behind a complex system...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.