OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef DataPersistent_h |
| 6 #define DataPersistent_h |
| 7 |
| 8 #include "platform/heap/Handle.h" |
| 9 #include "wtf/Allocator.h" |
| 10 #include "wtf/OwnPtr.h" |
| 11 |
| 12 namespace blink { |
| 13 |
| 14 // DataPersistent<T> provides the copy-on-modify behavior of DataRef<>, |
| 15 // but for Persistent<> heap references. |
| 16 // |
| 17 // That is, the DataPersistent<T> copy assignment, |a = b;|, makes |a| |
| 18 // share a reference to the T object that |b| holds until |a| is mutated |
| 19 // and access() on it is called. Or, dually, if |b| is mutated after the |
| 20 // assignment that mutation isn't observable to |a| but will be performed |
| 21 // on a copy of the underlying T object. |
| 22 // |
| 23 // DataPersistent<T> does assume that no one keeps non-DataPersistent<> shared |
| 24 // references to the underlying T object that it manages, and is mutating the |
| 25 // object via those. |
| 26 template <typename T> |
| 27 class DataPersistent { |
| 28 USING_FAST_MALLOC(DataPersistent); |
| 29 public: |
| 30 DataPersistent() |
| 31 : m_ownCopy(false) |
| 32 { |
| 33 } |
| 34 |
| 35 DataPersistent(const DataPersistent& other) |
| 36 : m_ownCopy(false) |
| 37 { |
| 38 if (other.m_data) |
| 39 m_data = adoptPtr(new Persistent<T>(other.m_data->get())); |
| 40 |
| 41 // Invalidated, subsequent mutations will happen on a new copy. |
| 42 // |
| 43 // (Clearing |m_ownCopy| will not be observable over T, hence |
| 44 // the const_cast<> is considered acceptable here.) |
| 45 const_cast<DataPersistent&>(other).m_ownCopy = false; |
| 46 } |
| 47 |
| 48 const T* get() const { return m_data ? m_data->get() : nullptr; } |
| 49 |
| 50 const T& operator*() const { return m_data ? *get() : nullptr; } |
| 51 const T* operator->() const { return get(); } |
| 52 |
| 53 T* access() |
| 54 { |
| 55 if (m_data && !m_ownCopy) { |
| 56 *m_data = (*m_data)->copy(); |
| 57 m_ownCopy = true; |
| 58 } |
| 59 return m_data ? m_data->get() : nullptr; |
| 60 } |
| 61 |
| 62 void init() |
| 63 { |
| 64 ASSERT(!m_data); |
| 65 m_data = adoptPtr(new Persistent<T>(T::create())); |
| 66 m_ownCopy = true; |
| 67 } |
| 68 |
| 69 bool operator==(const DataPersistent<T>& o) const |
| 70 { |
| 71 ASSERT(m_data); |
| 72 ASSERT(o.m_data); |
| 73 return m_data->get() == o.m_data->get() || *m_data->get() == *o.m_data->
get(); |
| 74 } |
| 75 |
| 76 bool operator!=(const DataPersistent<T>& o) const |
| 77 { |
| 78 ASSERT(m_data); |
| 79 ASSERT(o.m_data); |
| 80 return m_data->get() != o.m_data->get() && *m_data->get() != *o.m_data->
get(); |
| 81 } |
| 82 |
| 83 void operator=(std::nullptr_t) { m_data.clear(); } |
| 84 private: |
| 85 // Reduce size of DataPersistent<> by delaying creation of Persistent<>. |
| 86 OwnPtr<Persistent<T>> m_data; |
| 87 unsigned m_ownCopy:1; |
| 88 }; |
| 89 |
| 90 } // namespace blink |
| 91 |
| 92 #endif // DataPersistent_h |
OLD | NEW |