1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkOnce.h" 9 #include "SkThreadPool.h" 10 #include "Test.h" 11 #include "TestClassDef.h" 12 13 static void add_five(int* x) { 14 *x += 5; 15 } 16 17 DEF_TEST(SkOnce_Singlethreaded, r) { 18 int x = 0; 19 20 SK_DECLARE_STATIC_ONCE(once); 21 // No matter how many times we do this, x will be 5. 22 SkOnce(&once, add_five, &x); 23 SkOnce(&once, add_five, &x); 24 SkOnce(&once, add_five, &x); 25 SkOnce(&once, add_five, &x); 26 SkOnce(&once, add_five, &x); 27 28 REPORTER_ASSERT(r, 5 == x); 29 } 30 31 struct AddFour { void operator()(int* x) { *x += 4; } }; 32 33 DEF_TEST(SkOnce_MiscFeatures, r) { 34 // Tests that we support functors and explicit SkOnceFlags. 35 int x = 0; 36 37 SkOnceFlag once = SK_ONCE_INIT; 38 SkOnce(&once, AddFour(), &x); 39 SkOnce(&once, AddFour(), &x); 40 SkOnce(&once, AddFour(), &x); 41 42 REPORTER_ASSERT(r, 4 == x); 43 } 44 45 static void add_six(int* x) { 46 *x += 6; 47 } 48 49 class Racer : public SkRunnable { 50 public: 51 SkOnceFlag* once; 52 int* ptr; 53 54 virtual void run() SK_OVERRIDE { 55 SkOnce(once, add_six, ptr); 56 } 57 }; 58 59 DEF_TEST(SkOnce_Multithreaded, r) { 60 const int kTasks = 16, kThreads = 4; 61 62 // Make a bunch of tasks that will race to be the first to add six to x. 63 Racer racers[kTasks]; 64 SK_DECLARE_STATIC_ONCE(once); 65 int x = 0; 66 for (int i = 0; i < kTasks; i++) { 67 racers[i].once = &once; 68 racers[i].ptr = &x; 69 } 70 71 // Let them race. 72 SkThreadPool pool(kThreads); 73 for (int i = 0; i < kTasks; i++) { 74 pool.add(&racers[i]); 75 } 76 pool.wait(); 77 78 // Only one should have done the +=. 79 REPORTER_ASSERT(r, 6 == x); 80 } 81