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