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 "SkRunnable.h" 10 #include "SkTaskGroup.h" 11 #include "Test.h" 12 13 static void add_five(int* x) { 14 *x += 5; 15 } 16 17 SK_DECLARE_STATIC_ONCE(st_once); 18 DEF_TEST(SkOnce_Singlethreaded, r) { 19 int x = 0; 20 21 // No matter how many times we do this, x will be 5. 22 SkOnce(&st_once, add_five, &x); 23 SkOnce(&st_once, add_five, &x); 24 SkOnce(&st_once, add_five, &x); 25 SkOnce(&st_once, add_five, &x); 26 SkOnce(&st_once, add_five, &x); 27 28 REPORTER_ASSERT(r, 5 == x); 29 } 30 31 static void add_six(int* x) { 32 *x += 6; 33 } 34 35 namespace { 36 37 class Racer : public SkRunnable { 38 public: 39 SkOnceFlag* once; 40 int* ptr; 41 42 void run() override { 43 SkOnce(once, add_six, ptr); 44 } 45 }; 46 47 } // namespace 48 49 SK_DECLARE_STATIC_ONCE(mt_once); 50 DEF_TEST(SkOnce_Multithreaded, r) { 51 const int kTasks = 16; 52 53 // Make a bunch of tasks that will race to be the first to add six to x. 54 Racer racers[kTasks]; 55 int x = 0; 56 for (int i = 0; i < kTasks; i++) { 57 racers[i].once = &mt_once; 58 racers[i].ptr = &x; 59 } 60 61 // Let them race. 62 SkTaskGroup tg; 63 for (int i = 0; i < kTasks; i++) { 64 tg.add(&racers[i]); 65 } 66 tg.wait(); 67 68 // Only one should have done the +=. 69 REPORTER_ASSERT(r, 6 == x); 70 } 71 72 static int gX = 0; 73 static void inc_gX() { gX++; } 74 75 SK_DECLARE_STATIC_ONCE(noarg_once); 76 DEF_TEST(SkOnce_NoArg, r) { 77 SkOnce(&noarg_once, inc_gX); 78 SkOnce(&noarg_once, inc_gX); 79 SkOnce(&noarg_once, inc_gX); 80 REPORTER_ASSERT(r, 1 == gX); 81 } 82