• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 // Test of gpr thread support.
20 
21 #include "src/core/util/thd.h"
22 
23 #include <grpc/support/sync.h>
24 #include <grpc/support/time.h>
25 
26 #include <atomic>
27 
28 #include "gtest/gtest.h"
29 #include "test/core/test_util/test_config.h"
30 
31 #define NUM_THREADS 100
32 
33 struct test {
34   gpr_mu mu;
35   int n;
36   int is_done;
37   gpr_cv done_cv;
38 };
39 
40 // A Thread body.   Decrement t->n, and if is becomes zero, set t->done.
thd_body1(void * v)41 static void thd_body1(void* v) {
42   struct test* t = static_cast<struct test*>(v);
43   gpr_mu_lock(&t->mu);
44   t->n--;
45   if (t->n == 0) {
46     t->is_done = 1;
47     gpr_cv_signal(&t->done_cv);
48   }
49   gpr_mu_unlock(&t->mu);
50 }
51 
52 // Test that we can create a number of threads, wait for them, and join them.
TEST(ThreadTest,CanCreateWaitAndJoin)53 TEST(ThreadTest, CanCreateWaitAndJoin) {
54   grpc_core::Thread thds[NUM_THREADS];
55   struct test t;
56   gpr_mu_init(&t.mu);
57   gpr_cv_init(&t.done_cv);
58   t.n = NUM_THREADS;
59   t.is_done = 0;
60   for (auto& th : thds) {
61     th = grpc_core::Thread("grpc_thread_body1_test", &thd_body1, &t);
62     th.Start();
63   }
64   gpr_mu_lock(&t.mu);
65   while (!t.is_done) {
66     gpr_cv_wait(&t.done_cv, &t.mu, gpr_inf_future(GPR_CLOCK_REALTIME));
67   }
68   gpr_mu_unlock(&t.mu);
69   for (auto& th : thds) {
70     th.Join();
71   }
72   ASSERT_EQ(t.n, 0);
73   gpr_mu_destroy(&t.mu);
74   gpr_cv_destroy(&t.done_cv);
75 }
76 
thd_body2(void *)77 static void thd_body2(void* /*v*/) {}
78 
79 // Test that we can create a number of threads and join them.
TEST(ThreadTest,CanCreateSomeAndJoinThem)80 TEST(ThreadTest, CanCreateSomeAndJoinThem) {
81   grpc_core::Thread thds[NUM_THREADS];
82   for (auto& th : thds) {
83     bool ok;
84     th = grpc_core::Thread("grpc_thread_body2_test", &thd_body2, nullptr, &ok);
85     ASSERT_TRUE(ok);
86     th.Start();
87   }
88   for (auto& th : thds) {
89     th.Join();
90   }
91 }
92 
93 // Test that we can create a thread with an AnyInvocable.
TEST(ThreadTest,CanCreateWithAnyInvocable)94 TEST(ThreadTest, CanCreateWithAnyInvocable) {
95   grpc_core::Thread thds[NUM_THREADS];
96   std::atomic<int> count_run{0};
97   for (auto& th : thds) {
98     bool ok;
99     th = grpc_core::Thread(
100         "grpc_thread_body2_test",
101         [&count_run]() { count_run.fetch_add(1, std::memory_order_relaxed); },
102         &ok);
103     ASSERT_TRUE(ok);
104     th.Start();
105   }
106   for (auto& th : thds) {
107     th.Join();
108   }
109   EXPECT_EQ(count_run.load(std::memory_order_relaxed), NUM_THREADS);
110 }
111 
main(int argc,char ** argv)112 int main(int argc, char** argv) {
113   grpc::testing::TestEnvironment env(&argc, argv);
114   ::testing::InitGoogleTest(&argc, argv);
115   return RUN_ALL_TESTS();
116 }
117