1

During code review of my demo, reviewer suggested to use atomic_fetch_max compatible with the proposal Atomic maximum/minimum:

template<typename T> T atomic_fetch_max(std::atomic<T>* obj, typename std::atomic<T>::value_type arg) noexcept { auto prev = *obj; while (prev < arg && !obj->compare_exchange_weak(prev, arg)) {} return prev; } 

instead of my code

template<typename T> void update_max(std::atomic<T>& max_value, T const& value) noexcept { T prev_value = max_value; while (prev_value < value && !max_value.compare_exchange_weak(prev_value, value)) {} } 

I tried to incorporate it into my demo and can't make it compiled. Please see the demo.

Two questions here related to the problem:

  1. Why the suggested version fails to compile? I can't get the reason from compiler messages (they are too long and I am not sure how to include them here, please update the question if you know the format, I will follow).
  2. What is the reason the updated version uses typename std::atomic<T>::value_type arg instead of plain T or even better T const & which makes arg referenced value const?
12
  • 1
    T by value makes sense for any(?) T that's worth using with std::atomic<>: trivially-copyable and small enough to be lock-free also means it can easily be passed in registers. You normally want this to inline anyway, but if not, pass by value should be efficient. Except maybe for objects the size of 2 pointers in some calling conventions. But most objects you're likely to want max on are single numbers, where passing by value is more efficient if there ever is a non-inline function call. Commented Jan 20, 2024 at 13:46
  • 2
    Ah, it doesn't compile because *obj produces a std::atomic<T> & which is what auto picks. godbolt.org/z/P4hhTTaYz They should have used obj->load() or better obj->load(std::memory_order_relaxed). All the other changes, like returning the old value and taking T (or value_type) by value make sense and seem like improvements to me. Except for using ...::value_type instead of T, that seems over-complicated especially when they're still just returning a T Commented Jan 20, 2024 at 13:55
  • 1
    I was answering part (2) first, about the non-atomic arg being T (by value) or const T & (by reference). Commented Jan 20, 2024 at 13:56
  • 1
    Apparently yes, see wg21.link/P0558R1 and the updated list of duplicates. (Took me a while to find one for why T instead of T const&.) Commented Jan 20, 2024 at 15:00
  • 1
    A couple of the answers on C++: Why pass-by-value is generally more efficient than pass-by-reference for built-in (i.e., C-like) types say similar things to my very first comment, about why T instead of T const &. (Or value_type instead of value_type const&). Instead of editing the duplicate list twice for this question, I waited until I'd found that Q&A as well as the one about P0558R1. Commented Jan 20, 2024 at 15:49

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.