| // Copyright 2018 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef V8_OBJECTS_SLOTS_ATOMIC_INL_H_ | 
 | #define V8_OBJECTS_SLOTS_ATOMIC_INL_H_ | 
 |  | 
 | #include "src/base/atomic-utils.h" | 
 | #include "src/objects/compressed-slots.h" | 
 | #include "src/objects/slots.h" | 
 |  | 
 | namespace v8 { | 
 | namespace internal { | 
 |  | 
 | // This class is intended to be used as a wrapper for elements of an array | 
 | // that is passed in to STL functions such as std::sort. It ensures that | 
 | // elements accesses are atomic. | 
 | // Usage example: | 
 | //   FixedArray array; | 
 | //   AtomicSlot start(array->GetFirstElementAddress()); | 
 | //   std::sort(start, start + given_length, | 
 | //             [](Tagged_t a, Tagged_t b) { | 
 | //               // Decompress a and b if necessary. | 
 | //               return my_comparison(a, b); | 
 | //             }); | 
 | // Note how the comparator operates on Tagged_t values, representing the raw | 
 | // data found at the given heap location, so you probably want to construct | 
 | // an Object from it. | 
 | class AtomicSlot : public SlotBase<AtomicSlot, Tagged_t> { | 
 |  public: | 
 |   // This class is a stand-in for "Address&" that uses custom atomic | 
 |   // read/write operations for the actual memory accesses. | 
 |   class Reference { | 
 |    public: | 
 |     explicit Reference(Tagged_t* address) : address_(address) {} | 
 |     Reference(const Reference&) V8_NOEXCEPT = default; | 
 |  | 
 |     Reference& operator=(const Reference& other) V8_NOEXCEPT { | 
 |       AsAtomicTagged::Relaxed_Store( | 
 |           address_, AsAtomicTagged::Relaxed_Load(other.address_)); | 
 |       return *this; | 
 |     } | 
 |     Reference& operator=(Tagged_t value) { | 
 |       AsAtomicTagged::Relaxed_Store(address_, value); | 
 |       return *this; | 
 |     } | 
 |  | 
 |     // Values of type AtomicSlot::reference must be implicitly convertible | 
 |     // to AtomicSlot::value_type. | 
 |     operator Tagged_t() const { return AsAtomicTagged::Relaxed_Load(address_); } | 
 |  | 
 |     void swap(Reference& other) { | 
 |       Tagged_t tmp = value(); | 
 |       AsAtomicTagged::Relaxed_Store(address_, other.value()); | 
 |       AsAtomicTagged::Relaxed_Store(other.address_, tmp); | 
 |     } | 
 |  | 
 |     bool operator<(const Reference& other) const { | 
 |       return value() < other.value(); | 
 |     } | 
 |  | 
 |     bool operator==(const Reference& other) const { | 
 |       return value() == other.value(); | 
 |     } | 
 |  | 
 |    private: | 
 |     Tagged_t value() const { return AsAtomicTagged::Relaxed_Load(address_); } | 
 |  | 
 |     Tagged_t* address_; | 
 |   }; | 
 |  | 
 |   // The rest of this class follows C++'s "RandomAccessIterator" requirements. | 
 |   // Most of the heavy lifting is inherited from SlotBase. | 
 |   using difference_type = int; | 
 |   using value_type = Tagged_t; | 
 |   using reference = Reference; | 
 |   using pointer = void*;  // Must be present, but should not be used. | 
 |   using iterator_category = std::random_access_iterator_tag; | 
 |  | 
 |   AtomicSlot() : SlotBase(kNullAddress) {} | 
 |   explicit AtomicSlot(Address address) : SlotBase(address) {} | 
 |   explicit AtomicSlot(ObjectSlot slot) : SlotBase(slot.address()) {} | 
 |   explicit AtomicSlot(MaybeObjectSlot slot) : SlotBase(slot.address()) {} | 
 |  | 
 |   Reference operator*() const { | 
 |     return Reference(reinterpret_cast<Tagged_t*>(address())); | 
 |   } | 
 |   Reference operator[](difference_type i) const { | 
 |     return Reference(reinterpret_cast<Tagged_t*>(address() + i * kTaggedSize)); | 
 |   } | 
 |  | 
 |   friend void swap(Reference lhs, Reference rhs) { lhs.swap(rhs); } | 
 |  | 
 |   friend difference_type operator-(AtomicSlot a, AtomicSlot b) { | 
 |     return static_cast<int>(a.address() - b.address()) / kTaggedSize; | 
 |   } | 
 | }; | 
 |  | 
 | }  // namespace internal | 
 | }  // namespace v8 | 
 |  | 
 | #endif  // V8_OBJECTS_SLOTS_ATOMIC_INL_H_ |