1

I want an asynchronous thread to edit an object. Therefore I store a pointer to that object.

Data *pointer;

There is also a flag of type std::atomic<bool> to know if the secondary thread is modifying the object the pointer points to or not. While the flag holds true, the main thread won't affect the pointer and its underlying object.

std::atomic<bool> modifying;

void Thread()
{
    // wait for jobs
    for(;;)
    {
        // the flag is set to true my the main thread
        // to let this thread start processing
        if(modifying)
        {
            // modify the object the pointer points to,
            // pass the pointer to a function to do so,
            // and so on...

            // the flag to false to tell the main thread
            // that it can read the result from the pointer
            // and prepare it for the next job
            modifying = false;
        }
    }
}
  • How can I ensure thread safety?

I cannot wrap the pointer by std::atomic because from the secondary thread I need to pass the pointer to a function expecting a non atomic Data* type as parameter.

  • Do pointers even need to be declared as atomic specifically? I don't think that a processor would change threads during writing a single register. Or do I have to make it atomic anyway to prevent unwanted compiler optimizations?
  • If a pointer is atomic, is the underlying object so, too? In other words, could I modify the object using the pointer I get from pointer.load()?

Thanks for your clarification.

14
  • I started writing an answer, but realized that I don't actually understand what you are doing. What changes the atomic value? What sort of changes? Are you actually trying to protect Data or the pointer to Data. The question really seems like you are trying to do something other than what atomic is meant for. Commented May 17, 2013 at 16:26
  • Basically, I want two thread to communicate via the pointer. The main thread sets data to point to an object and starts another thread. This other thread changes the object the pointer points to. That's all. I would use a pointer wrapped by atomic for that but I cannot pass that to the function I want to call from within the other thread. I hope it is clearer now. Commented May 17, 2013 at 16:31
  • Ok, but I think I'll formulate an answer that is not based on atomic, because I don't see how atomic is meaningful in this case. Commented May 17, 2013 at 16:35
  • Would be great. As I mentioned in the question, I haven't understand atomic pointers completely. They might not be the way to go in this case. Commented May 17, 2013 at 16:37
  • 1
    Well, I was heading towards a mutex answer, but I guess I don't need to provid that as an answer now. Still looks like you are wasting CPU time in the Thread code. Commented May 17, 2013 at 17:12

1 Answer 1

1

It sounds like what you want is to have the privilege to edit the object be mutually exclusive. This is exactly what mutexes were made for.

In general, suppose you have threads A and B, both of which want to update the same pointer. When, e.g., A wants to make an edit, it tries to lock() the mutex. If the mutex isn't already locked by B, this will succeed, and A can do its thing. If the mutex is already locked by B, then A will block (that is, stop executing) until B releases its lock on the mutex, at which point A will continue and do its thing as normal.

For a more concrete example of the syntax of C++11's mutexes, this page does a good job: http://en.cppreference.com/w/cpp/thread/mutex

And, of course, I would recommend the pthreads library for an explanation of mutexes (and other threading concepts) in general: https://computing.llnl.gov/tutorials/pthreads/#Mutexes

In your case, your code might look something like this:

std::mutex editing;

void Thread()
{
    for(;;)
    {
        editing.lock();

        // Do whatever editing you wanted to do here.

        editing.unlock();
    }
}

It's also worth noting the try_lock() function on the std::mutex class. This is very similar to lock(), except if the mutex is already locked then it will just return false to indicate that the lock couldn't be acquired, and continue. This would be useful if you want your thread to just forget about editing the object and continue if the other thread is already editing the object, instead of waiting for the other thread and then editing.

Sign up to request clarification or add additional context in comments.

3 Comments

This is totally safe, as long as you don't try to edit the pointer from somewhere else that doesn't respect your mutex. The compiler will optimize as much as it can, I'm sure, but that won't make this operation non-thread-safe.
So I can safely use bare pointers? Regardless of whether I use mutex or a similar construct.
Basically, you lock the mutex. At this point, you can do absolutely whatever you want to the pointer, safe in the knowledge that nobody else will touch it until you're done. When you're done, you unlock the mutex, opening it back up to be modified by other threads. Making the pointer atomic is unnecessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.