Michal Czardybon
Michal Czardybon

Reputation: 2865

Can I safely write a constant value to a variable from multiple threads in C++?

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:

  1. The main reason I use a function pointer is to remove some dependencies between modules. This is a small element of a big real project. I really can't call 'foo' directly.
  2. I know how to program and I do not need basic information about things like mutex. My question is whether this is safe WITHOUT mutex.
  3. It is guaranteed in the code that no other thread sets the pointer to anything other than &foo.

Upvotes: 2

Views: 267

Answers (3)

Lingxi
Lingxi

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

Pandrei
Pandrei

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

Cory Kramer
Cory Kramer

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

Related Questions