diff options
-rw-r--r-- | gyp/tests.gypi | 1 | ||||
-rw-r--r-- | src/core/SkLazyPtr.h | 23 | ||||
-rw-r--r-- | tests/LazyPtr.cpp | 48 | ||||
-rw-r--r-- | tests/OnceTest.cpp | 4 |
4 files changed, 71 insertions, 5 deletions
diff --git a/gyp/tests.gypi b/gyp/tests.gypi index 6ae2027d55..422a22e2ce 100644 --- a/gyp/tests.gypi +++ b/gyp/tests.gypi @@ -130,6 +130,7 @@ '../tests/LListTest.cpp', '../tests/LayerDrawLooperTest.cpp', '../tests/LayerRasterizerTest.cpp', + '../tests/LazyPtr.cpp', '../tests/MD5Test.cpp', '../tests/MallocPixelRefTest.cpp', '../tests/MathTest.cpp', diff --git a/src/core/SkLazyPtr.h b/src/core/SkLazyPtr.h index 594112f6ac..f9508c5973 100644 --- a/src/core/SkLazyPtr.h +++ b/src/core/SkLazyPtr.h @@ -8,7 +8,7 @@ #ifndef SkLazyPtr_DEFINED #define SkLazyPtr_DEFINED -/** Declare a lazily-chosen static pointer (or array of pointers) of type F. +/** Declare a lazily-chosen static pointer (or array of pointers) of type T. * * Example usage: * @@ -49,7 +49,7 @@ */ #define SK_DECLARE_STATIC_LAZY_PTR(T, name, ...) \ - namespace {} static Private::SkLazyPtr<T, ##__VA_ARGS__> name + namespace {} static Private::SkLazyPtrBase<T, ##__VA_ARGS__> name #define SK_DECLARE_STATIC_LAZY_PTR_ARRAY(T, name, N, ...) \ namespace {} static Private::SkLazyPtrArray<T, N, ##__VA_ARGS__> name @@ -58,7 +58,6 @@ // problems with them in function-local statics because it uses -fno-threadsafe-statics, and even // in builds with threadsafe statics, those threadsafe statics are just unnecessary overhead. - // Everything below here is private implementation details. Don't touch, don't even look. #include "SkDynamicAnnotations.h" @@ -103,7 +102,7 @@ template <typename T> void sk_delete(T* ptr) { SkDELETE(ptr); } // This has no constructor and must be zero-initalized (the macro above does this). template <typename T, T* (*Create)() = sk_new<T>, void (*Destroy)(T*) = sk_delete<T> > -class SkLazyPtr { +class SkLazyPtrBase { public: T* get() { // If fPtr has already been filled, we need a consume barrier when loading it. @@ -112,7 +111,7 @@ public: return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create()); } -private: +protected: void* fPtr; }; @@ -136,4 +135,18 @@ private: } // namespace Private +// This version is suitable for use as a class member. +// It's the same as above except it has a constructor to zero itself and a destructor to clean up. +template <typename T, + T* (*Create)() = Private::sk_new<T>, + void (*Destroy)(T*) = Private::sk_delete<T> > +class SkLazyPtr : public Private::SkLazyPtrBase<T, Create, Destroy> { +public: + SkLazyPtr() { INHERITED::fPtr = NULL; } + ~SkLazyPtr() { if (INHERITED::fPtr) { Destroy((T*)INHERITED::fPtr); } } +private: + typedef Private::SkLazyPtrBase<T, Create, Destroy> INHERITED; +}; + + #endif//SkLazyPtr_DEFINED diff --git a/tests/LazyPtr.cpp b/tests/LazyPtr.cpp new file mode 100644 index 0000000000..ff235e6ed3 --- /dev/null +++ b/tests/LazyPtr.cpp @@ -0,0 +1,48 @@ +#include "Test.h" +#include "SkLazyPtr.h" +#include "SkTaskGroup.h" + +DEF_TEST(LazyPtr, r) { + SkLazyPtr<int> lazy; + int* ptr = lazy.get(); + + REPORTER_ASSERT(r, ptr); + REPORTER_ASSERT(r, lazy.get() == ptr); + + SkLazyPtr<double> neverRead; +} + +namespace { + +struct Racer : public SkRunnable { + Racer() : fLazy(NULL), fSeen(NULL) {} + + virtual void run() SK_OVERRIDE { fSeen = fLazy->get(); } + + SkLazyPtr<int>* fLazy; + int* fSeen; +}; + +} // namespace + +DEF_TEST(LazyPtr_Threaded, r) { + static const int kRacers = 321; + + SkLazyPtr<int> lazy; + + Racer racers[kRacers]; + for (int i = 0; i < kRacers; i++) { + racers[i].fLazy = &lazy; + } + + SkTaskGroup tg; + for (int i = 0; i < kRacers; i++) { + tg.add(racers + i); + } + tg.wait(); + + for (int i = 1; i < kRacers; i++) { + REPORTER_ASSERT(r, racers[i].fSeen); + REPORTER_ASSERT(r, racers[i].fSeen == racers[0].fSeen); + } +} diff --git a/tests/OnceTest.cpp b/tests/OnceTest.cpp index 192abaaee3..e2711f00bb 100644 --- a/tests/OnceTest.cpp +++ b/tests/OnceTest.cpp @@ -31,6 +31,8 @@ static void add_six(int* x) { *x += 6; } +namespace { + class Racer : public SkRunnable { public: SkOnceFlag* once; @@ -41,6 +43,8 @@ public: } }; +} // namespace + DEF_TEST(SkOnce_Multithreaded, r) { const int kTasks = 16; |