Index: third_party/WebKit/Source/core/style/DataPersistent.h |
diff --git a/third_party/WebKit/Source/core/style/DataPersistent.h b/third_party/WebKit/Source/core/style/DataPersistent.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b97a41a5d251331631771b147aef6da7b140043d |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/style/DataPersistent.h |
@@ -0,0 +1,92 @@ |
+// Copyright 2016 The Chromium 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 DataPersistent_h |
+#define DataPersistent_h |
+ |
+#include "platform/heap/Handle.h" |
+#include "wtf/Allocator.h" |
+#include "wtf/OwnPtr.h" |
+ |
+namespace blink { |
+ |
+// DataPersistent<T> provides the copy-on-modify behavior of DataRef<>, |
+// but for Persistent<> heap references. |
+// |
+// That is, the DataPersistent<T> copy assignment, |a = b;|, makes |a| |
+// share a reference to the T object that |b| holds until |a| is mutated |
+// and access() on it is called. Or, dually, if |b| is mutated after the |
+// assignment that mutation isn't observable to |a| but will be performed |
+// on a copy of the underlying T object. |
+// |
+// DataPersistent<T> does assume that no one keeps non-DataPersistent<> shared |
+// references to the underlying T object that it manages, and is mutating the |
+// object via those. |
+template <typename T> |
+class DataPersistent { |
+ USING_FAST_MALLOC(DataPersistent); |
+public: |
+ DataPersistent() |
+ : m_ownCopy(false) |
+ { |
+ } |
+ |
+ DataPersistent(const DataPersistent& other) |
+ : m_ownCopy(false) |
+ { |
+ if (other.m_data) |
+ m_data = adoptPtr(new Persistent<T>(other.m_data->get())); |
+ |
+ // Invalidated, subsequent mutations will happen on a new copy. |
+ // |
+ // (Clearing |m_ownCopy| will not be observable over T, hence |
+ // the const_cast<> is considered acceptable here.) |
+ const_cast<DataPersistent&>(other).m_ownCopy = false; |
+ } |
+ |
+ const T* get() const { return m_data ? m_data->get() : nullptr; } |
+ |
+ const T& operator*() const { return m_data ? *get() : nullptr; } |
+ const T* operator->() const { return get(); } |
+ |
+ T* access() |
+ { |
+ if (m_data && !m_ownCopy) { |
+ *m_data = (*m_data)->copy(); |
+ m_ownCopy = true; |
+ } |
+ return m_data ? m_data->get() : nullptr; |
+ } |
+ |
+ void init() |
+ { |
+ ASSERT(!m_data); |
+ m_data = adoptPtr(new Persistent<T>(T::create())); |
+ m_ownCopy = true; |
+ } |
+ |
+ bool operator==(const DataPersistent<T>& o) const |
+ { |
+ ASSERT(m_data); |
+ ASSERT(o.m_data); |
+ return m_data->get() == o.m_data->get() || *m_data->get() == *o.m_data->get(); |
+ } |
+ |
+ bool operator!=(const DataPersistent<T>& o) const |
+ { |
+ ASSERT(m_data); |
+ ASSERT(o.m_data); |
+ return m_data->get() != o.m_data->get() && *m_data->get() != *o.m_data->get(); |
+ } |
+ |
+ void operator=(std::nullptr_t) { m_data.clear(); } |
+private: |
+ // Reduce size of DataPersistent<> by delaying creation of Persistent<>. |
+ OwnPtr<Persistent<T>> m_data; |
+ unsigned m_ownCopy:1; |
+}; |
+ |
+} // namespace blink |
+ |
+#endif // DataPersistent_h |