Do thread_local variables need to be locked using a mutex? - c++

I considered thread_local variables as private variables for each thread, just with the same name. But all examples I found use a mutex variable to lock the thread_local variable when accessing it. This confused me. If thread_local is private for each thread, there is no need to take care of the concurrency problem, or my acknowledgement of the "private" idea is wrong?
Example taken from here:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
thread_local unsigned int rage = 1;
std::mutex cout_mutex;
void increase_rage(const std::string& thread_name)
{
++rage;
std::lock_guard<std::mutex> lock(cout_mutex);
std::cout << "Rage counter for " << thread_name << ": " << rage << '\n';
}
int main()
{
std::thread a(increase_rage, "a"), b(increase_rage, "b");
increase_rage("main");
a.join();
b.join();
}
In this case, is it necessary to lock the thread_local variable?

If you take a pointer to a thread_local object, and pass the pointer to another thread, in some way, the other thread can still access the original thread's thread_local object using the pointer (until the originating thread terminates, after which point this becames undefined behavior).
So, if this can happen in your application, you will still need to arrange for mutex protection, or something equivalent, in order to access the thread_local object in a thread-safe manner.

Naming thread_local variables private variables is a bit unfortunate.
A thread_local declared variable is owned by its thread and not accessible by other threads unless the owner thread (for some reason) gives them a pointer to that variable.
A thread_local variable is shared among all functions of its thread; i.e. it has its lifetime. If a thread_local variable is constructed it will be destroyed when its thread exits.
A thread_local variable can be static, in which case some care should be taken to make sure the program executes as expected. I won't go into this, since it is not part of the question.
The mutex in your example, as pointed out in the comments, is not for a data race condition. It is to synchronize the console output: the mutex is called cout_mutex - self explaining.

Related

winapi: get callback when thread ends

I have some c++ library code that creates some book-keeping data per thread that accesses it (based on thread-id). I would like to cleanup that data when a thread ends. Is there a way (if not portable, then using win-api) to get notified when a thread ends?
// simplified example:
std::mutex mutex_;
std::unordered_map<std::thread::id, int> thread_accesses_;
void LibFunction() {
std::thread::id thread_id = std::this_thread::get_id();
mutex_.lock();
std::unordered_map<std::thread::id, int>::const_iterator it = thread_accesses_.find(thread_id);
if(it == thread_accesses_.end()) {
thread_accesses_[thread_id] = 0;
} else {
thread_accesses_[thread_id]++;
}
mutex_.unlock();
}
Thread-local storage is both C++ standard way and platform way.
C++ has thread_local keyword to declare thread-local variable. Then destructor of that variable is called for each thread for which it was constructed. Thread local variable is constructed for at least all threads that access the variable, and possibly for other threads.
Windows has thread-local storage as system mechanism. thread_local is implemented via this mechanism.
It is possible to have thread exit callbacks in Windows by other means:
having thread-local data and TLS callbacks in module by other means
Using DllMain callbacks
Passing FlsCallback in FlsAlloc, fiber local storage is something superior to thread local storage, and in absence of fibers it behaves exactly like thread local storage
If cannot use thread_local, but want something simple and portable, consider also boost::thread_specific_ptr.

Singleton pattern with atomic states

Is it a correct way to make singleton objects by using 2 static atomic and mutex variables to save 2 states: initializing and initialized?
For example, I only need one Application instance running in a program. Its job is to init and terminate external libraries, and prevent to create any new Application object.
#include <mutex>
#include <stdexcept>
static bool initialized;
static std::mutex mutex;
Application::Application()
{
std::lock_guard<std::mutex> lock(mutex);
if (initialized) throw std::runtime_error("Application::Application");
if (!init_external_libraries())
throw std::runtime_error("Application::Application");
initialized = true;
}
Application::~Application()
{
terminiate_external_libraries();
initialized = false;
}
Do I get it right, that init_external_libraries() has to run at most one time?
Atomics won't help you there. Operations on atomics are atomic (storing and loading values in your case), but what happens between those is not.
You could use that nice trick of having a function that has a static object and returns a reference to it. As far as I know, initialization of static values are guaranteed to happen only once.
It would look something like this:
Object &get_singleton(){
static Object o;
return o;
}
EDIT: And, as far as I know, this is threadsafe. Don't quote me on that though.

std::lock_guard example, explanation on why it works

I've reached a point in my project that requires communication between threads on resources that very well may be written to, so synchronization is a must. However I don't really understand synchronization at anything other than the basic level.
Consider the last example in this link: http://www.bogotobogo.com/cplusplus/C11/7_C11_Thread_Sharing_Memory.php
#include <iostream>
#include <thread>
#include <list>
#include <algorithm>
#include <mutex>
using namespace std;
// a global variable
std::list<int>myList;
// a global instance of std::mutex to protect global variable
std::mutex myMutex;
void addToList(int max, int interval)
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
void printList()
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr ) {
cout << *itr << ",";
}
}
int main()
{
int max = 100;
std::thread t1(addToList, max, 1);
std::thread t2(addToList, max, 10);
std::thread t3(printList);
t1.join();
t2.join();
t3.join();
return 0;
}
The example demonstrates how three threads, two writers and one reader, accesses a common resource(list).
Two global functions are used: one which is used by the two writer threads, and one being used by the reader thread. Both functions use a lock_guard to lock down the same resource, the list.
Now here is what I just can't wrap my head around: The reader uses a lock in a different scope than the two writer threads, yet still locks down the same resource. How can this work? My limited understanding of mutexes lends itself well to the writer function, there you got two threads using the exact same function. I can understand that, a check is made right as you are about to enter the protected area, and if someone else is already inside, you wait.
But when the scope is different? This would indicate that there is some sort of mechanism more powerful than the process itself, some sort of runtime environment blocking execution of the "late" thread. But I thought there were no such things in c++. So I am at a loss.
What exactly goes on under the hood here?
Let’s have a look at the relevant line:
std::lock_guard<std::mutex> guard(myMutex);
Notice that the lock_guard references the global mutex myMutex. That is, the same mutex for all three threads. What lock_guard does is essentially this:
Upon construction, it locks myMutex and keeps a reference to it.
Upon destruction (i.e. when the guard's scope is left), it unlocks myMutex.
The mutex is always the same one, it has nothing to do with the scope. The point of lock_guard is just to make locking and unlocking the mutex easier for you. For example, if you manually lock/unlock, but your function throws an exception somewhere in the middle, it will never reach the unlock statement. So, doing it the manual way you have to make sure that the mutex is always unlocked. On the other hand, the lock_guard object gets destroyed automatically whenever the function is exited – regardless how it is exited.
myMutex is global, which is what is used to protect myList. guard(myMutex) simply engages the lock and the exit from the block causes its destruction, dis-engaging the lock. guard is just a convenient way to engage and dis-engage the lock.
With that out of the way, mutex does not protect any data. It just provides a way to protect data. It is the design pattern that protects data. So if I write my own function to modify the list as below, the mutex cannot protect it.
void addToListUnsafe(int max, int interval)
{
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
The lock only works if all pieces of code that need to access the data engage the lock before accessing and disengage after they are done. This design-pattern of engaging and dis-engaging the lock before and after every access is what protects the data (myList in your case)
Now you would wonder, why use mutex at all, and why not, say, a bool. And yes you can, but you will have to make sure that the bool variable will exhibit certain characteristics including but not limited to the below list.
Not be cached (volatile) across multiple threads.
Read and write will be atomic operation.
Your lock can handle situation where there are multiple execution pipelines (logical cores, etc).
There are different synchronization mechanisms that provide "better locking" (across processes versus across threads, multiple processor versus, single processor, etc) at a cost of "slower performance", so you should always choose a locking mechanism which is just about enough for your situation.
Just to add onto what others here have said...
There is an idea in C++ called Resource Acquisition Is Initialization (RAII) which is this idea of binding resources to the lifetime of objects:
Resource Acquisition Is Initialization or RAII, is a C++ programming technique which binds the life cycle of a resource that must be acquired before use (allocated heap memory, thread of execution, open socket, open file, locked mutex, disk space, database connection—anything that exists in limited supply) to the lifetime of an object.
C++ RAII Info
The use of a std::lock_guard<std::mutex> class follows the RAII idea.
Why is this useful?
Consider a case where you don't use a std::lock_guard:
std::mutex m; // global mutex
void oops() {
m.lock();
doSomething();
m.unlock();
}
in this case, a global mutex is used and is locked before the call to doSomething(). Then once doSomething() is complete the mutex is unlocked.
One problem here is what happens if there is an exception? Now you run the risk of never reaching the m.unlock() line which releases the mutex to other threads.
So you need to cover the case where you run into an exception:
std::mutex m; // global mutex
void oops() {
try {
m.lock();
doSomething();
m.unlock();
} catch(...) {
m.unlock(); // now exception path is covered
// throw ...
}
}
This works but is ugly, verbose, and inconvenient.
Now lets write our own simple lock guard.
class lock_guard {
private:
std::mutex& m;
public:
lock_guard(std::mutex& m_):(m(m_)){ m.lock(); } // lock on construction
~lock_guard() { t.unlock(); }} // unlock on deconstruction
}
When the lock_guard object is destroyed, it will ensure that the mutex is unlocked.
Now we can use this lock_guard to handle the case from before in a better/cleaner way:
std::mutex m; // global mutex
void ok() {
lock_guard lk(m); // our simple lock guard, protects against exception case
doSomething();
} // when scope is exited our lock guard object is destroyed and the mutex unlocked
This is the same idea behind std::lock_guard.
Again this approach is used with many different types of resources which you can read more about by following the link on RAII.
This is precisely what a lock does. When a thread takes the lock, regardless of where in the code it does so, it must wait its turn if another thread holds the lock. When a thread releases a lock, regardless of where in the code it does so, another thread may acquire that lock.
Locks protect data, not code. They do it by ensuring all code that accesses the protected data does so while it holds the lock, excluding other threads from any code that might access that same data.

Can a C++11 thread_local variable inherit its initial value from the parent thread?

I'd like to have a thread_local variable to change the level of logging applied in each thread of my application. Something like so:
enum class trace_level { none, error, warning, log, debug, verbose };
static thread_local trace_level min_level = trace_level::log;
The default value should be trace_level::log for the main thread when the application starts, but if it is changed before launching other threads, then I would like the child threads to start with the current value of the parent.
Is there any way to do this using a thread_local variable? Since this code is buried in a library it is not an option to simply set the value manually at the start of each thread.
This already happens if the initialization is dynamic. The standard requires that variables with "thread storage duration" and dynamic initialization be initialized sometime between the start of the thread and the 'first odr-use'. However, since you generally can't control exactly when that initialization will occur (other than sometime after the thread object is created and sometime before the thread ends - assuming the thread local variable actually gets used by the thread) the problem is that the thread local variable might get initialized with a value that your main thread sets after the thread is created.
For a concrete example, consider:
#include <stdio.h>
#include <chrono>
#include <functional>
#include <thread>
#include <string>
using std::string;
enum class trace_level { none, error, warning, log, debug, verbose };
trace_level log_level = trace_level::log;
static thread_local trace_level min_level = log_level;
void f(string const& s)
{
printf("%s, min_level == %d\n", s.c_str(), (int) min_level);
}
int main()
{
std::thread t1{std::bind(f,"thread 1")};
//TODO: std::this_thread::sleep_for(std::chrono::milliseconds(50));
log_level = trace_level::verbose;
std::thread t2{std::bind(f,"thread 2")};
t1.join();
t2.join();
}
With the sleep_for() call commented out as above, I get the following output (usually):
C:\so-test>test
thread 1, min_level == 5
thread 2, min_level == 5
However, with the sleep_for() uncommented, I get (again - usually):
C:\so-test>test
thread 1, min_level == 3
thread 2, min_level == 5
So as long as you're willing to live with a bit of uncertainty regarding which logging level a thread will get if the level gets changed in the main thread soon after the thread starts, you can probably just do what you're looking to do pretty naturally.
There's one remaining caveat - data races. The code above has a data race on the log_level variable, so it actually has undefined behavior. The fix for that is to make the variable either an atomic type or wrap it in a class that uses a mutex to protect updates and reads from data races. So change the declaration of the global log_level to:
std::atomic<trace_level> log_level(trace_level::log);
Standards citations:
3.6.2 Initialization of non-local variables [basic.start.init]
... Non-local variables with thread storage duration are initialized
as a consequence of thread execution. ...
and
3.7.2/2 Thread storage duration [basic.stc.thread]
A variable with thread storage duration shall be initialized before
its first odr-use (3.2) and, if constructed, shall be destroyed on
thread exit.
You can create a global pointer to a parent thread local variable.
In global scope
thread_local trace_level min_level = trace_level::log;
trace_level *min_level_ptr = nullptr;
Then, in each thread you can do:
if (!min_level_ptr)
min_level_ptr = &min_level;
else
min_level = *min_level_ptr;
(Possibly, make the min_level_ptr atomic for added safety and use atomic compare exchange instead of assignment).
The idea goes as following: each thread's local storage occupies a different region in memory, so min_level variable in one thread has unique storage address different from all other. min_level_ptr, on the other hand, has the same address, no matter which thread is accessing it. As "parent" thread starts before all other, it will claim the globally shared pointer with its own min_level address. The children will then initialize their values from that location.

What is critical resources to a std::mutex object

I am new to concurrency and I am having doubts in std::mutex. Say I've a int a; and books are telling me to declare a mutex amut; to get exclusive access over a. Now my question is how a mutex object is recognizing which critical resources it has to protect ? I mean which variable?
say I've two variables int a,b; now i declare mutex abmut; Now abmut will protect what???
both a and b or only a or b???
Your doubts are justified: it doesn't. That's your job as a programmer, to make sure you only access a if you've got the mutex. If somebody else got the mutex, do not access a or you will have the same problems you'd have without the mutex. That goes for all thread-syncronization constructs. You can use them to protect a resource. They don't do it on their own.
Mutex is more like a sign rather than a lock. When someone sees a sign saying "occupied" in a public washroom, he will wait until the user gets out and flips the sign. But you have to teach him to wait when seeing the sign. The sign itself won't prevent him from breaking in. Of course, the "wait" order is already set by mutex.lock(), so you can use it conveniently.
A std::mutex does not protect any data at all. A mutex works like this:
When you try to lock a mutex you look if the mutex is not already locked, else you wait until it is unlocked.
When you're finished using a mutex you unlock it, else threads that are waiting will do that forever.
How does that protect things? consider the following:
#include <iostream>
#include <future>
#include <vector>
struct example {
static int shared_variable;
static void incr_shared()
{
for(int i = 0; i < 100000; i++)
{
shared_variable++;
}
}
};
int example::shared_variable = 0;
int main() {
std::vector<std::future<void> > handles;
handles.reserve(10000);
for(int i = 0; i < 10000; i++) {
handles.push_back(std::async(std::launch::async, example::incr_shared));
}
for(auto& handle: handles) handle.wait();
std::cout << example::shared_variable << std::endl;
}
You might expect it to print 1000000000, but you don't really have a guarantee of that. We should include a mutex, like this:
struct example {
static int shared_variable;
static std::mutex guard;
static void incr_shared()
{
std::lock_guard<std::mutex>{ guard };
for(int i = 0; i < 100000; i++)
{
shared_variable++;
}
}
};
So what does this exactly do? First of all std::lock_guard uses RAII to call mutex.lock() when it's created and mutex.unlock when it's destroyed, this last one happens when it leaves scope (here when the function exits). So in this case only one thread can be executing the for loop because as soon as a thread passes the lock_guard it holds the lock, and we saw before that no other thread can hold it. Therefore this loop is now safe. Note that we could also put the lock_guard inside the loop, but that might make your program slow (locking and unlocking is relatively expensive).
So in conclusion, a mutex protects blocks of code, in our example the for-loop, not the variable itself. If you want variable protection, consider taking a look at std::atomic. The following example is for example again unsafe because decr_shared can be called simultaneously from any thread.
struct example {
static int shared_variable;
static std::mutex guard;
static void decr_shared() { shared_variable--; }
static void incr_shared()
{
std::lock_guard<std::mutex>{ guard };
for(int i = 0; i < 100000; i++)
{
shared_variable++;
}
}
};
This however is again safe, because now the variable itself is protected, in any code that uses it.
struct example {
static std::atomic_int shared_variable;
static void decr_shared() { shared_variable--; }
static void incr_shared()
{
for(int i = 0; i < 100000; i++)
{
shared_variable++;
}
}
};
std::atomic_int example::shared_variable{0};
A mutex doesn't inherently protect any specific variables... instead, the programmer needs to realise that they have some group of 1 or more variables that several threads may attempt to use, then use a mutex so that only one of those threads can be running such variable-using/changing code at any point in time.
Note especially that you're only protected from other threads' code accessing/modifying those variables if their code locks the same mutex during the variable access. A mutex used by only one thread protects nothing.
mutex is used to synchronize access to a resource. Say you have a data say int, where you are going to do read write operation using an getter and a setter. So both getter and setters will use the same mutex to to sync read/write operation.
both of these function will lock the mutex at the beginning and unlock it before it returns. you can use scoped_lock that will automatically unlock on its destructor.
void setter(value_type v){
boost::mutex::scoped_lock lock(mutex);
value = v;
}
value_type getter() const{
boost::mutex::scoped_lock lock(mutex);
return value;
}
Imagine you sit at a table with your friends and a delicious cake (the resources you want to guard, e.g. some integer a) in the middle. In addition you have a single tennis ball (this is our mutex). Now, only a single person can have the ball (lock the mutex using a lock_guard or similar mechanisms), but everyone can eat the cake (access the integer a).
As a group you can decide to set up a rule that only whoever has the ball may eat from the cake (only the person who has locked the mutex may access a). This person may relinquish the ball by putting it on the table (unlock the mutex), so another person can grab it (lock the mutex). This way you ensure that no one stabs another person with the fork, while frantically eating the cake.
Setting up and upholding a rule like described in the last paragraph is your job as a programmer. There is no inherent connection between a mutex and some resource (e.g. some integer a).