13a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com/*
23a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com * Copyright 2013 Google Inc.
33a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com *
43a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com * Use of this source code is governed by a BSD-style license that can be
53a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com * found in the LICENSE file.
63a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com */
73a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
83a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com#include "SkOnce.h"
93a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com#include "SkThreadPool.h"
103a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com#include "Test.h"
113a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
121f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.orgstatic void add_five(int* x) {
133a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    *x += 5;
143a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com}
153a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
163a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.comDEF_TEST(SkOnce_Singlethreaded, r) {
173a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    int x = 0;
183a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
191f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SK_DECLARE_STATIC_ONCE(once);
203a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    // No matter how many times we do this, x will be 5.
211f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SkOnce(&once, add_five, &x);
221f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SkOnce(&once, add_five, &x);
231f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SkOnce(&once, add_five, &x);
241f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SkOnce(&once, add_five, &x);
251f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SkOnce(&once, add_five, &x);
263a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
273a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    REPORTER_ASSERT(r, 5 == x);
283a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com}
293a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
301f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.orgstatic void add_six(int* x) {
313a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    *x += 6;
323a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com}
333a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
343a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.comclass Racer : public SkRunnable {
353a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.compublic:
361f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SkOnceFlag* once;
373a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    int* ptr;
381f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org
393a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    virtual void run() SK_OVERRIDE {
401f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org        SkOnce(once, add_six, ptr);
413a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    }
423a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com};
433a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
443a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.comDEF_TEST(SkOnce_Multithreaded, r) {
453a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    const int kTasks = 16, kThreads = 4;
463a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
473a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    // Make a bunch of tasks that will race to be the first to add six to x.
483a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    Racer racers[kTasks];
491f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    SK_DECLARE_STATIC_ONCE(once);
503a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    int x = 0;
513a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    for (int i = 0; i < kTasks; i++) {
521f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org        racers[i].once = &once;
533a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com        racers[i].ptr = &x;
543a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    }
553a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
563a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    // Let them race.
57a7538baeae619a513437f89b60cf738ee2de463dcommit-bot@chromium.org    SkThreadPool pool(kThreads);
583a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    for (int i = 0; i < kTasks; i++) {
59a7538baeae619a513437f89b60cf738ee2de463dcommit-bot@chromium.org        pool.add(&racers[i]);
603a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    }
61a7538baeae619a513437f89b60cf738ee2de463dcommit-bot@chromium.org    pool.wait();
623a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com
633a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    // Only one should have done the +=.
643a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com    REPORTER_ASSERT(r, 6 == x);
653a19fb58a68183ea855439bdc92da4b90592c6a1mtklein@google.com}
66709ca75f032d7c60eb53c5840524a875a3a6cdb1commit-bot@chromium.org
671b81877880253c75f835eede9a8ee21b9e7b584amtkleinstatic int gX = 0;
681b81877880253c75f835eede9a8ee21b9e7b584amtkleinstatic void inc_gX() { gX++; }
69709ca75f032d7c60eb53c5840524a875a3a6cdb1commit-bot@chromium.org
701b81877880253c75f835eede9a8ee21b9e7b584amtkleinDEF_TEST(SkOnce_NoArg, r) {
71709ca75f032d7c60eb53c5840524a875a3a6cdb1commit-bot@chromium.org    SK_DECLARE_STATIC_ONCE(once);
721b81877880253c75f835eede9a8ee21b9e7b584amtklein    SkOnce(&once, inc_gX);
731b81877880253c75f835eede9a8ee21b9e7b584amtklein    SkOnce(&once, inc_gX);
741b81877880253c75f835eede9a8ee21b9e7b584amtklein    SkOnce(&once, inc_gX);
751b81877880253c75f835eede9a8ee21b9e7b584amtklein    REPORTER_ASSERT(r, 1 == gX);
76709ca75f032d7c60eb53c5840524a875a3a6cdb1commit-bot@chromium.org}
77