Fix SkTCopyOnFirstWrite copy semantics
The implicit SkTCopyOnFirstWrite copy-ctor and assignment operator are incorrect: fObj must point to the local copy, not to the source copy (when a copy has been made). Add corrected explicit copy (and move) ctor + assignment operator. Also add a get() helper to facilitate rawptr access. Change-Id: Ie3983e12c04eae4f32c40e3e267618cf02008c20 Reviewed-on: https://skia-review.googlesource.com/120442 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
2b67005be0
commit
8eaf64ae12
@ -265,6 +265,7 @@ tests_sources = [
|
||||
"$_tests/TextureProxyTest.cpp",
|
||||
"$_tests/TextureStripAtlasManagerTest.cpp",
|
||||
"$_tests/Time.cpp",
|
||||
"$_tests/TLazyTest.cpp",
|
||||
"$_tests/TopoSortTest.cpp",
|
||||
"$_tests/ToSRGBColorFilter.cpp",
|
||||
"$_tests/TraceMemoryDumpTest.cpp",
|
||||
|
@ -148,13 +148,28 @@ private:
|
||||
template <typename T>
|
||||
class SkTCopyOnFirstWrite {
|
||||
public:
|
||||
SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
|
||||
explicit SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
|
||||
|
||||
SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}
|
||||
explicit SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}
|
||||
|
||||
// Constructor for delayed initialization.
|
||||
SkTCopyOnFirstWrite() : fObj(nullptr) {}
|
||||
|
||||
SkTCopyOnFirstWrite(const SkTCopyOnFirstWrite& that) { *this = that; }
|
||||
SkTCopyOnFirstWrite( SkTCopyOnFirstWrite&& that) { *this = std::move(that); }
|
||||
|
||||
SkTCopyOnFirstWrite& operator=(const SkTCopyOnFirstWrite& that) {
|
||||
fLazy = that.fLazy;
|
||||
fObj = fLazy.isValid() ? fLazy.get() : that.fObj;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SkTCopyOnFirstWrite& operator=(SkTCopyOnFirstWrite&& that) {
|
||||
fLazy = std::move(that.fLazy);
|
||||
fObj = fLazy.isValid() ? fLazy.get() : that.fObj;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Should only be called once, and only if the default constructor was used.
|
||||
void init(const T& initial) {
|
||||
SkASSERT(nullptr == fObj);
|
||||
@ -174,6 +189,8 @@ public:
|
||||
return const_cast<T*>(fObj);
|
||||
}
|
||||
|
||||
const T* get() const { return fObj; }
|
||||
|
||||
/**
|
||||
* Operators for treating this as though it were a const pointer.
|
||||
*/
|
||||
|
77
tests/TLazyTest.cpp
Normal file
77
tests/TLazyTest.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkTLazy.h"
|
||||
#include "Test.h"
|
||||
|
||||
DEF_TEST(TLazy_copy, r) {
|
||||
SkTLazy<int> lazy;
|
||||
|
||||
REPORTER_ASSERT(r, !lazy.isValid());
|
||||
REPORTER_ASSERT(r, lazy.getMaybeNull() == nullptr);
|
||||
|
||||
{
|
||||
SkTLazy<int> lazy_copy(lazy);
|
||||
REPORTER_ASSERT(r, !lazy_copy.isValid());
|
||||
REPORTER_ASSERT(r, lazy_copy.getMaybeNull() == nullptr);
|
||||
}
|
||||
|
||||
lazy.init(42);
|
||||
|
||||
REPORTER_ASSERT(r, lazy.isValid());
|
||||
REPORTER_ASSERT(r, 42 == *lazy.get());
|
||||
|
||||
{
|
||||
SkTLazy<int> lazy_copy(lazy);
|
||||
REPORTER_ASSERT(r, lazy_copy.isValid());
|
||||
REPORTER_ASSERT(r, 42 == *lazy_copy.get());
|
||||
REPORTER_ASSERT(r, lazy.get() != lazy_copy.get());
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(TCopyOnFirstWrite_copy, r) {
|
||||
const int v = 42;
|
||||
|
||||
SkTCopyOnFirstWrite<int> cow(v);
|
||||
|
||||
REPORTER_ASSERT(r, 42 == *cow);
|
||||
REPORTER_ASSERT(r, &v == cow.get());
|
||||
|
||||
{
|
||||
SkTCopyOnFirstWrite<int> cow_copy(cow);
|
||||
REPORTER_ASSERT(r, 42 == *cow_copy);
|
||||
REPORTER_ASSERT(r, &v == cow_copy.get());
|
||||
REPORTER_ASSERT(r, cow.get() == cow_copy.get());
|
||||
|
||||
*cow_copy.writable() = 43;
|
||||
REPORTER_ASSERT(r, 42 == *cow);
|
||||
REPORTER_ASSERT(r, &v == cow.get());
|
||||
REPORTER_ASSERT(r, 43 == *cow_copy);
|
||||
REPORTER_ASSERT(r, &v != cow_copy.get());
|
||||
REPORTER_ASSERT(r, cow.get() != cow_copy.get());
|
||||
}
|
||||
|
||||
*cow.writable() = 43;
|
||||
|
||||
REPORTER_ASSERT(r, 43 == *cow);
|
||||
REPORTER_ASSERT(r, &v != cow.get());
|
||||
|
||||
{
|
||||
SkTCopyOnFirstWrite<int> cow_copy(cow);
|
||||
REPORTER_ASSERT(r, 43 == *cow_copy);
|
||||
REPORTER_ASSERT(r, &v != cow_copy.get());
|
||||
REPORTER_ASSERT(r, cow.get() != cow_copy.get());
|
||||
|
||||
*cow_copy.writable() = 44;
|
||||
|
||||
REPORTER_ASSERT(r, 43 == *cow);
|
||||
REPORTER_ASSERT(r, &v != cow.get());
|
||||
REPORTER_ASSERT(r, 44 == *cow_copy);
|
||||
REPORTER_ASSERT(r, &v != cow_copy.get());
|
||||
REPORTER_ASSERT(r, cow.get() != cow_copy.get());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user