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