HazptrWideCAS.h 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. /*
  2. * Copyright 2016-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <folly/synchronization/Hazptr.h>
  18. #include <string>
  19. namespace folly {
  20. /** Wide CAS.
  21. */
  22. template <typename T, template <typename> class Atom = std::atomic>
  23. class HazptrWideCAS {
  24. struct Node : public hazptr_obj_base<Node, Atom> {
  25. T val_;
  26. explicit Node(T v = {}) : val_(v) {}
  27. };
  28. Atom<Node*> node_;
  29. public:
  30. HazptrWideCAS() : node_(new Node()) {}
  31. ~HazptrWideCAS() {
  32. delete node_.load(std::memory_order_relaxed);
  33. }
  34. bool cas(T& u, T& v) {
  35. Node* n = new Node(v);
  36. hazptr_holder<Atom> hptr;
  37. Node* p;
  38. while (true) {
  39. p = hptr.get_protected(node_);
  40. if (p->val_ != u) {
  41. delete n;
  42. return false;
  43. }
  44. if (node_.compare_exchange_weak(
  45. p, n, std::memory_order_relaxed, std::memory_order_release)) {
  46. break;
  47. }
  48. }
  49. hptr.reset();
  50. p->retire();
  51. return true;
  52. }
  53. };
  54. } // namespace folly