nsubiron
nsubiron

Reputation: 923

Atomic load and store with memory order relaxed

Everywhere I read I see strong recommendations not to use relaxed memory order, I wonder whether the following piece of code is one of this exceptions in which this will work, or there are any ramifications I'm not seeing.

class SessionHolder {
public:

  void set_session(std::shared_ptr<Session> session) {
    std::atomic_store_explicit(&_session, session, std::memory_order_relaxed);
  }

  std::shared_ptr<Session> get_session() const {
    return std::atomic_load_explicit(&_session, std::memory_order_relaxed);
  }

private:

  std::shared_ptr<Session> _session;
};

In principle, when I do a get_session, I don't care which session I'm getting as long as it is a session or nullptr. But if another thread does a store (which happens rarely), I would like to eventually get that value within a reasonable delay.

More context on how this class is used:

Basically, I have some sort of stream that is continuously producing data. At a certain point a client process may connect (start a session) and start listening to this data. The producer thread is continuously writing to the stream, if there is no active session the data is discarded, else sent to the client. Another thread, at certain point (not often), when a client connects reaches to this stream and sets the session.

The producer thread must have as little contention as possible, even if that means missing a few messages.

Upvotes: 2

Views: 758

Answers (1)

Brian Bi
Brian Bi

Reputation: 119059

As I understand, it is not even guaranteed that I would get that value, just that I will get a value that was stored there at some point in time, but I could always get nullptr.

Yes, it's hypothetically possible that every call to get_session will return a null pointer, but unlikely. One guarantee that even relaxed memory order offers is that once a particular thread observes a value, the same thread cannot subsequently observe a previous value. Thus, once a particular thread starts to observe a non-null pointer, that thread will always observe a non-null pointer in subsequent calls to get_session (assuming that a null pointer is never stored).

In practice seems to work, can I expect it to fail (always retrieving nullptr) in some situations/platform specifically?

Not that I'm aware of.

Can I adjust the memory order in the store operation only to fix this? e.g. memory_order_release would spread the changes to the other thread?

No. The standard does not provide any method to ensure that inter-thread communication is completed within any particular amount of time. Only the implementation can provide such a guarantee.

One final note: nullptr is not the same as "a null pointer". It's a special constant of a unique type that can be converted to a null pointer of another type.

Upvotes: 2

Related Questions