7

Since we have rvalue references in C++0x it seems to me that it should be possible to implement std::swap as an atomic operation with CAS. Is this the case in the new standard, and if not why?

ronag
  • 49,529
  • 25
  • 126
  • 221
  • 1
    It is either C++11 or C++0x, not C++1x. – kennytm Aug 10 '10 at 07:41
  • 2
    Why would rvalue references make something atomic? - please post some code. –  Aug 10 '10 at 07:43
  • @KennyTM: ##C++ on freenode calls it C++1x – the_drow Aug 10 '10 at 07:45
  • @Neil: Thought the official name was updated – the_drow Aug 10 '10 at 07:49
  • 1
    With CAS you can implement *everything* as atomic. Whether you want to do it or not is a whole different story. – David Rodríguez - dribeas Aug 10 '10 at 07:51
  • @the_drow: When? The latest official document that mentions C++?? is still using the term C++0x (N3095, 2010 Apr). – kennytm Aug 10 '10 at 07:55
  • @Neil Butterworth: Because rvalue references and std::move just replaces the memory address, which can also be done with CAS. I might be wrong, that's why I'm asking. – ronag Aug 10 '10 at 07:58
  • @the_drow: there is no official name. C++0x and all its variants are nicknames for what might become a standard in a year or two. As such, there is no way it can be "updated". People can call it whatever they like. I still call it C++0x because it avoids confusion, and because googling for C++0x gives me *all* references to the draft standard, including those from a couple of years ago. C++1x is also ambiguous. It is likely that we are going to se more than one revision to the standard this decade. So does 1x refer to C++11 or, say, C++17? – jalf Aug 10 '10 at 11:45

3 Answers3

8

It is not atomic. Atomic operations are not cheap and 99% of the time you do not need the atomicity. There are (IIRC) some other means to get atomic operations but std::swap() is not one of them.

wilx
  • 17,697
  • 6
  • 59
  • 114
  • Would it be possible to implement an std::atomic_swap for any type in C++0x? If soo, how? – ronag Aug 10 '10 at 08:21
  • @ronag - the simplest way would be a global mutex on the swap operation. ;-) – Omnifarious Aug 10 '10 at 08:35
  • @ronag: I agree with Omnifarious. In fact, I think that that is pretty much the only viable option. – wilx Aug 10 '10 at 10:21
  • @ronag: some platforms will be able to provide lock-free swapping for some types (up to a certain size). This should all be handled by a decent implementation of `std::atomic_exchange`, and you can check whether this uses a lock using `std::atomic::is_lock_free()`. – Mike Seymour Aug 10 '10 at 12:17
  • 2
    @Omnifarious: Global lock on `swap` is not sufficient. `atomic_swap` has to be atomic with respect to all object modifications (e.g. `push_back`) not just other swaps. – Ben Jackson Apr 18 '13 at 23:54
5

Simple answer no, not really.

While you can use CAS to implement atomic operations, in most cases you would have to redesign part of the implementation to do so, and you will, in most cases, have an impact in performance in all usages.

Consider a current implementation of a vector in g++. It keeps three pointers: begin, end, end_of_capacity. How would you make swap atomic for such a vector? You could simplify things by pushing all three pointers into a dynamically allocated block of memory, and then implementing an atomic swap would be simpler, just swap the pointers. The problem is that you have added an extra memory allocation to the container and an extra dereference operation in each and every access through the container (iterators would perform similar to the original implementation).

Do read at this answer by FredOverflow for a simple explanation on move semantics.

Community
  • 1
  • 1
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • You forget that with rvalue references and std::move it just swaps the memory address. I might be wrong. – ronag Aug 10 '10 at 08:01
  • Had it only swapped memory addresses, we wouldn't have to define Move Constructor for complex types. As far as I imagine, it may only swap memory addresses when dealing with temporary POD declared on the stack in a fonction needing to return that precise POD type. But in other cases, it calls the Move constructor. Well... I think so. – Stephane Rolland Aug 10 '10 at 08:25
  • 1
    @ronag: You're wrong. How does one swap memory addresses? At some point (namely, with primitives), moving has to be the same as copying. And that is the case. – GManNickG Aug 10 '10 at 08:26
  • Thank you for clearing that up, seems I have misunderstood how rvalues work. I will have to study this a bit more in-depth. – ronag Aug 10 '10 at 08:32
  • 2
    @ronag: [shameless plug](http://stackoverflow.com/questions/3106110/can-someone-please-explain-move-semantics-to-me/3109981#3109981) – fredoverflow Aug 10 '10 at 08:35
  • @FredOverflow: No need to shame on you, that is a nice answer, well related and deserves any upvote it might get! I am adding the link to the answer so that you do not need any more shame. – David Rodríguez - dribeas Aug 10 '10 at 09:01
1

Not every class can have a move assignment operator which can be implemented more efficiently than the regular assignment operator. Case in point std::array which has a native array as a member. Another case is a std::string where the small string optimization is used (for small strings).

Therefore generally you can't say anything about std::swap with move semantics that you couldn't say about std::swap in C++98. For some cases it will be better but not for the general case.

Motti
  • 110,860
  • 49
  • 189
  • 262