1*09537850SAkhilesh Sanikop // Copyright 2021 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop // http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop
15*09537850SAkhilesh Sanikop #include "src/utils/blocking_counter.h"
16*09537850SAkhilesh Sanikop
17*09537850SAkhilesh Sanikop #include <array>
18*09537850SAkhilesh Sanikop #include <memory>
19*09537850SAkhilesh Sanikop
20*09537850SAkhilesh Sanikop #include "absl/time/clock.h"
21*09537850SAkhilesh Sanikop #include "absl/time/time.h"
22*09537850SAkhilesh Sanikop #include "gtest/gtest.h"
23*09537850SAkhilesh Sanikop #include "src/utils/threadpool.h"
24*09537850SAkhilesh Sanikop
25*09537850SAkhilesh Sanikop namespace libgav1 {
26*09537850SAkhilesh Sanikop namespace {
27*09537850SAkhilesh Sanikop
28*09537850SAkhilesh Sanikop constexpr int kNumWorkers = 10;
29*09537850SAkhilesh Sanikop constexpr int kNumJobs = 20;
30*09537850SAkhilesh Sanikop
TEST(BlockingCounterTest,BasicFunctionality)31*09537850SAkhilesh Sanikop TEST(BlockingCounterTest, BasicFunctionality) {
32*09537850SAkhilesh Sanikop std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
33*09537850SAkhilesh Sanikop BlockingCounter counter(kNumJobs);
34*09537850SAkhilesh Sanikop std::array<bool, kNumJobs> done = {};
35*09537850SAkhilesh Sanikop
36*09537850SAkhilesh Sanikop // Schedule the jobs.
37*09537850SAkhilesh Sanikop for (int i = 0; i < kNumJobs; ++i) {
38*09537850SAkhilesh Sanikop pool->Schedule([&counter, &done, i]() {
39*09537850SAkhilesh Sanikop absl::SleepFor(absl::Seconds(1));
40*09537850SAkhilesh Sanikop done[i] = true;
41*09537850SAkhilesh Sanikop counter.Decrement();
42*09537850SAkhilesh Sanikop });
43*09537850SAkhilesh Sanikop }
44*09537850SAkhilesh Sanikop
45*09537850SAkhilesh Sanikop // Wait for the jobs to complete. This should always return true.
46*09537850SAkhilesh Sanikop ASSERT_TRUE(counter.Wait());
47*09537850SAkhilesh Sanikop
48*09537850SAkhilesh Sanikop // Make sure the jobs were actually complete.
49*09537850SAkhilesh Sanikop for (const auto& job_done : done) {
50*09537850SAkhilesh Sanikop EXPECT_TRUE(job_done);
51*09537850SAkhilesh Sanikop }
52*09537850SAkhilesh Sanikop }
53*09537850SAkhilesh Sanikop
TEST(BlockingCounterTest,IncrementBy)54*09537850SAkhilesh Sanikop TEST(BlockingCounterTest, IncrementBy) {
55*09537850SAkhilesh Sanikop std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
56*09537850SAkhilesh Sanikop BlockingCounter counter(0);
57*09537850SAkhilesh Sanikop std::array<bool, kNumJobs> done = {};
58*09537850SAkhilesh Sanikop
59*09537850SAkhilesh Sanikop // Schedule the jobs.
60*09537850SAkhilesh Sanikop for (int i = 0; i < kNumJobs; ++i) {
61*09537850SAkhilesh Sanikop counter.IncrementBy(1);
62*09537850SAkhilesh Sanikop pool->Schedule([&counter, &done, i]() {
63*09537850SAkhilesh Sanikop absl::SleepFor(absl::Seconds(1));
64*09537850SAkhilesh Sanikop done[i] = true;
65*09537850SAkhilesh Sanikop counter.Decrement();
66*09537850SAkhilesh Sanikop });
67*09537850SAkhilesh Sanikop }
68*09537850SAkhilesh Sanikop
69*09537850SAkhilesh Sanikop // Wait for the jobs to complete. This should always return true.
70*09537850SAkhilesh Sanikop ASSERT_TRUE(counter.Wait());
71*09537850SAkhilesh Sanikop
72*09537850SAkhilesh Sanikop // Make sure the jobs were actually complete.
73*09537850SAkhilesh Sanikop for (const auto& job_done : done) {
74*09537850SAkhilesh Sanikop EXPECT_TRUE(job_done);
75*09537850SAkhilesh Sanikop }
76*09537850SAkhilesh Sanikop }
77*09537850SAkhilesh Sanikop
TEST(BlockingCounterWithStatusTest,BasicFunctionality)78*09537850SAkhilesh Sanikop TEST(BlockingCounterWithStatusTest, BasicFunctionality) {
79*09537850SAkhilesh Sanikop std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
80*09537850SAkhilesh Sanikop BlockingCounterWithStatus counter(kNumJobs);
81*09537850SAkhilesh Sanikop std::array<bool, kNumJobs> done = {};
82*09537850SAkhilesh Sanikop
83*09537850SAkhilesh Sanikop // Schedule the jobs.
84*09537850SAkhilesh Sanikop for (int i = 0; i < kNumJobs; ++i) {
85*09537850SAkhilesh Sanikop pool->Schedule([&counter, &done, i]() {
86*09537850SAkhilesh Sanikop absl::SleepFor(absl::Seconds(1));
87*09537850SAkhilesh Sanikop done[i] = true;
88*09537850SAkhilesh Sanikop counter.Decrement(true);
89*09537850SAkhilesh Sanikop });
90*09537850SAkhilesh Sanikop }
91*09537850SAkhilesh Sanikop
92*09537850SAkhilesh Sanikop // Wait for the jobs to complete. This should return true since all the jobs
93*09537850SAkhilesh Sanikop // reported |job_succeeded| as true.
94*09537850SAkhilesh Sanikop ASSERT_TRUE(counter.Wait());
95*09537850SAkhilesh Sanikop
96*09537850SAkhilesh Sanikop // Make sure the jobs were actually complete.
97*09537850SAkhilesh Sanikop for (const auto& job_done : done) {
98*09537850SAkhilesh Sanikop EXPECT_TRUE(job_done);
99*09537850SAkhilesh Sanikop }
100*09537850SAkhilesh Sanikop }
101*09537850SAkhilesh Sanikop
TEST(BlockingCounterWithStatusTest,BasicFunctionalityWithStatus)102*09537850SAkhilesh Sanikop TEST(BlockingCounterWithStatusTest, BasicFunctionalityWithStatus) {
103*09537850SAkhilesh Sanikop std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
104*09537850SAkhilesh Sanikop BlockingCounterWithStatus counter(kNumJobs);
105*09537850SAkhilesh Sanikop std::array<bool, kNumJobs> done = {};
106*09537850SAkhilesh Sanikop
107*09537850SAkhilesh Sanikop // Schedule the jobs.
108*09537850SAkhilesh Sanikop for (int i = 0; i < kNumJobs; ++i) {
109*09537850SAkhilesh Sanikop pool->Schedule([&counter, &done, i]() {
110*09537850SAkhilesh Sanikop absl::SleepFor(absl::Seconds(1));
111*09537850SAkhilesh Sanikop done[i] = true;
112*09537850SAkhilesh Sanikop counter.Decrement(i != 10);
113*09537850SAkhilesh Sanikop });
114*09537850SAkhilesh Sanikop }
115*09537850SAkhilesh Sanikop
116*09537850SAkhilesh Sanikop // Wait for the jobs to complete. This should return false since one of the
117*09537850SAkhilesh Sanikop // jobs reported |job_succeeded| as false.
118*09537850SAkhilesh Sanikop ASSERT_FALSE(counter.Wait());
119*09537850SAkhilesh Sanikop
120*09537850SAkhilesh Sanikop // Make sure the jobs were actually complete.
121*09537850SAkhilesh Sanikop for (const auto& job_done : done) {
122*09537850SAkhilesh Sanikop EXPECT_TRUE(job_done);
123*09537850SAkhilesh Sanikop }
124*09537850SAkhilesh Sanikop }
125*09537850SAkhilesh Sanikop
126*09537850SAkhilesh Sanikop } // namespace
127*09537850SAkhilesh Sanikop } // namespace libgav1
128