skia2/tests/LazyPtrTest.cpp
mtklein 00b621cfc0 Add sk_parallel_for()
This should be a drop-in replacement for most for-loops to make them run in parallel:
   for (int i = 0; i < N; i++) { code... }
   ~~~>
   sk_parallel_for(N, [&](int i) { code... });

This is just syntax sugar over SkTaskGroup to make this use case really easy to write.
There's no more overhead that we weren't already forced to add using an interface like batch(),
and no extra heap allocations.

I've replaced 3 uses of SkTaskGroup with sk_parallel_for:
  1) My unit tests for SkOnce.
  2) Cary's path fuzzer.
  3) SkMultiPictureDraw.
Performance should be the same.  Please compare left and right for readability. :)

BUG=skia:

No public API changes.
TBR=reed@google.com

Review URL: https://codereview.chromium.org/1184373003
2015-06-17 15:26:15 -07:00

71 lines
1.8 KiB
C++

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Test.h"
#include "SkLazyPtr.h"
#include "SkRunnable.h"
#include "SkTaskGroup.h"
namespace {
struct CreateIntFromFloat {
CreateIntFromFloat(float val) : fVal(val) {}
int* operator()() const { return SkNEW_ARGS(int, ((int)fVal)); }
float fVal;
};
// As a template argument this must have external linkage.
void custom_destroy(int* ptr) { *ptr = 99; }
} // namespace
DEF_TEST(LazyPtr, r) {
// Basic usage: calls SkNEW(int).
SkLazyPtr<int> lazy;
int* ptr = lazy.get();
REPORTER_ASSERT(r, ptr);
REPORTER_ASSERT(r, lazy.get() == ptr);
// Advanced usage: calls a functor.
SkLazyPtr<int> lazyFunctor;
int* six = lazyFunctor.get(CreateIntFromFloat(6.4f));
REPORTER_ASSERT(r, six);
REPORTER_ASSERT(r, 6 == *six);
// Just makes sure this is safe.
SkLazyPtr<double> neverRead;
// SkLazyPtr supports custom destroy methods.
{
SkLazyPtr<int, custom_destroy> customDestroy;
ptr = customDestroy.get();
// custom_destroy called here.
}
REPORTER_ASSERT(r, ptr);
REPORTER_ASSERT(r, 99 == *ptr);
// Since custom_destroy didn't actually delete ptr, we do now.
SkDELETE(ptr);
}
DEF_TEST(LazyPtr_Threaded, r) {
static const int kRacers = 321;
// Race to intialize the pointer by calling .get().
SkLazyPtr<int> lazy;
int* seen[kRacers];
sk_parallel_for(kRacers, [&](int i) {
seen[i] = lazy.get();
});
// lazy.get() should return the same pointer to all threads.
for (int i = 1; i < kRacers; i++) {
REPORTER_ASSERT(r, seen[i] != nullptr);
REPORTER_ASSERT(r, seen[i] == seen[0]);
}
}