aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkTLazy.h
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-11 19:32:32 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-11 19:32:32 +0000
commit5dc26b97366934ba0f896cea02a3fec027d5d5c1 (patch)
treef9be03e4ed22947191a696269d4d735d0a06a52e /include/core/SkTLazy.h
parentb364eb6c871c88710534c444cc4f075fcb9e3c02 (diff)
SkTCopyOnFirstWrite
R=reed@google.com Review URL: https://codereview.appspot.com/6650047 git-svn-id: http://skia.googlecode.com/svn/trunk@5905 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'include/core/SkTLazy.h')
-rw-r--r--include/core/SkTLazy.h54
1 files changed, 54 insertions, 0 deletions
diff --git a/include/core/SkTLazy.h b/include/core/SkTLazy.h
index cf2d943829..cd1e8f2b9c 100644
--- a/include/core/SkTLazy.h
+++ b/include/core/SkTLazy.h
@@ -88,5 +88,59 @@ private:
char fStorage[sizeof(T)];
};
+/**
+ * A helper built on top of SkTLazy to do copy-on-first-write. The object is initialized
+ * with a const pointer but provides a non-const pointer accessor. The first time the
+ * accessor is called (if ever) the object is cloned.
+ *
+ * In the following example at most one copy of constThing is made:
+ *
+ * SkTCopyOnFirstWrite<Thing> thing(&constThing);
+ * ...
+ * function_that_takes_a_const_thing_ptr(thing); // constThing is passed
+ * ...
+ * if (need_to_modify_thing()) {
+ * thing.writable()->modifyMe(); // makes a copy of constThing
+ * }
+ * ...
+ * x = thing->readSomething();
+ * ...
+ * if (need_to_modify_thing_now()) {
+ * thing.writable()->changeMe(); // makes a copy of constThing if we didn't call modifyMe()
+ * }
+ *
+ * consume_a_thing(thing); // could be constThing or a modified copy.
+ */
+template <typename T>
+class SkTCopyOnFirstWrite {
+public:
+ SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
+
+ /**
+ * Returns a writable T*. The first time this is called the initial object is cloned.
+ */
+ T* writable() {
+ if (!fLazy.isValid()) {
+ fLazy.set(*fObj);
+ fObj = fLazy.get();
+ }
+ return const_cast<T*>(fObj);
+ }
+
+ /**
+ * Operators for treating this as though it were a const pointer.
+ */
+
+ const T *operator->() const { return fObj; }
+
+ operator const T*() const { return fObj; }
+
+ const T& operator *() const { return *fObj; }
+
+private:
+ const T* fObj;
+ SkTLazy<T> fLazy;
+};
+
#endif