Reputation: 2865
In particular, I want to set a value of a function pointer. For simplicity, I want to do it many times, from multiple threads, but always in a simple manner like this:
typedef void (*F)();
F f = 0;
void foo()
{
}
// called many times from multiple threads
void set()
{
f = &foo;
}
int main()
{
set(); // also other threads can invoke it at any time
f();
return 0;
}
Thus, initially the function pointer is NULL and then becomes &foo when the code is executed for the first time. I wonder if due to any non-atomic write operation the function pointer may become disrupted.
It is guaranteed that it will be read for the first time after it is set.
EDIT: I clarify:
Upvotes: 2
Views: 267
Reputation: 14987
The standard says your code invokes undefined behavior. But in your particular case, i.e., with your particular compiler and architecture, your code may actually be problem-free. So, from a theoretical point of view, your code is not OK. From a practical point of view, the answer depends on your specific case and is by no means general. Personally, I suggest replacing F f = 0;
with std::atomic<F> f(0);
so that the code is guaranteed to be OK in all cases.
Just to illustrate a case where your code breaks: The implementation may choose to clear the target before each write operation. Such an implementation is legal and conforms to the standard, though not necessarily award-winning :)
Upvotes: 2
Reputation: 4961
I think this is more of a thread synchronization problem than a c++ related one. The answer to your question is, yes you can write a value to a varaible/pointer safely in c++ (Not sure what you mean by constant; it looks to me like you simply want to assign a function pointer), you simply have to use mutual exclusion so that the threads don't overwrite the value when you don't want them to
Depending on what you ultimately want to achieve, you may need more than one mutex (i.e if you want to ensure a certain order in which the threads assign the function pointer), but this is definitely the way to safely do it.
Upvotes: 0
Reputation: 118001
Have you considered use a std::mutex
and std::lock_guard
to enforce thread safety?
For example
{
std::lock_guard<std::mutex> lg(my_mutex);
f = &foo;
// then use f to perform your operation
}
After the closing brace, the lock_guard
falls out of scope and unlocks your mutex
. This means that whoever sets f
can then use that function pointer safely knowing that another thread hasn't changed the function pointer between setting it and trying to use it.
Upvotes: 4