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 |