| /* |
| * Copyright 2013 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkOnce.h" |
| #include "SkThreadPool.h" |
| #include "Test.h" |
| |
| static void add_five(int* x) { |
| *x += 5; |
| } |
| |
| DEF_TEST(SkOnce_Singlethreaded, r) { |
| int x = 0; |
| |
| SK_DECLARE_STATIC_ONCE(once); |
| // No matter how many times we do this, x will be 5. |
| SkOnce(&once, add_five, &x); |
| SkOnce(&once, add_five, &x); |
| SkOnce(&once, add_five, &x); |
| SkOnce(&once, add_five, &x); |
| SkOnce(&once, add_five, &x); |
| |
| REPORTER_ASSERT(r, 5 == x); |
| } |
| |
| struct AddFour { void operator()(int* x) { *x += 4; } }; |
| |
| DEF_TEST(SkOnce_MiscFeatures, r) { |
| // Tests that we support functors and explicit SkOnceFlags. |
| int x = 0; |
| |
| SkOnceFlag once = SK_ONCE_INIT; |
| SkOnce(&once, AddFour(), &x); |
| SkOnce(&once, AddFour(), &x); |
| SkOnce(&once, AddFour(), &x); |
| |
| REPORTER_ASSERT(r, 4 == x); |
| } |
| |
| static void add_six(int* x) { |
| *x += 6; |
| } |
| |
| class Racer : public SkRunnable { |
| public: |
| SkOnceFlag* once; |
| int* ptr; |
| |
| virtual void run() SK_OVERRIDE { |
| SkOnce(once, add_six, ptr); |
| } |
| }; |
| |
| DEF_TEST(SkOnce_Multithreaded, r) { |
| const int kTasks = 16, kThreads = 4; |
| |
| // Make a bunch of tasks that will race to be the first to add six to x. |
| Racer racers[kTasks]; |
| SK_DECLARE_STATIC_ONCE(once); |
| int x = 0; |
| for (int i = 0; i < kTasks; i++) { |
| racers[i].once = &once; |
| racers[i].ptr = &x; |
| } |
| |
| // Let them race. |
| SkThreadPool pool(kThreads); |
| for (int i = 0; i < kTasks; i++) { |
| pool.add(&racers[i]); |
| } |
| pool.wait(); |
| |
| // Only one should have done the +=. |
| REPORTER_ASSERT(r, 6 == x); |
| } |
| |
| // Test that the atExit option works. |
| static int gToDecrement = 1; |
| static void noop(int) {} |
| static void decrement() { gToDecrement--; } |
| static void checkDecremented() { SkASSERT(gToDecrement == 0); } |
| |
| DEF_TEST(SkOnce_atExit, r) { |
| atexit(checkDecremented); |
| SK_DECLARE_STATIC_ONCE(once); |
| SkOnce(&once, noop, 0, decrement); |
| } |