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