Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include <cstring>
6 :
7 : #include "src/base/platform/platform.h"
8 : #include "src/base/platform/semaphore.h"
9 : #include "src/base/platform/time.h"
10 : #include "testing/gtest/include/gtest/gtest.h"
11 :
12 : namespace v8 {
13 : namespace base {
14 :
15 : namespace {
16 :
17 : static const char kAlphabet[] = "XKOAD";
18 : static const size_t kAlphabetSize = sizeof(kAlphabet) - 1;
19 : static const size_t kBufferSize = 987; // GCD(buffer size, alphabet size) = 1
20 : static const size_t kDataSize = kBufferSize * kAlphabetSize * 10;
21 :
22 :
23 1 : class ProducerThread final : public Thread {
24 : public:
25 : ProducerThread(char* buffer, Semaphore* free_space, Semaphore* used_space)
26 : : Thread(Options("ProducerThread")),
27 : buffer_(buffer),
28 : free_space_(free_space),
29 1 : used_space_(used_space) {}
30 :
31 1 : void Run() override {
32 98701 : for (size_t n = 0; n < kDataSize; ++n) {
33 49350 : free_space_->Wait();
34 49350 : buffer_[n % kBufferSize] = kAlphabet[n % kAlphabetSize];
35 49350 : used_space_->Signal();
36 : }
37 1 : }
38 :
39 : private:
40 : char* buffer_;
41 : Semaphore* const free_space_;
42 : Semaphore* const used_space_;
43 : };
44 :
45 :
46 1 : class ConsumerThread final : public Thread {
47 : public:
48 : ConsumerThread(const char* buffer, Semaphore* free_space,
49 : Semaphore* used_space)
50 : : Thread(Options("ConsumerThread")),
51 : buffer_(buffer),
52 : free_space_(free_space),
53 1 : used_space_(used_space) {}
54 :
55 1 : void Run() override {
56 98701 : for (size_t n = 0; n < kDataSize; ++n) {
57 49350 : used_space_->Wait();
58 98700 : EXPECT_EQ(kAlphabet[n % kAlphabetSize], buffer_[n % kBufferSize]);
59 49350 : free_space_->Signal();
60 : }
61 1 : }
62 :
63 : private:
64 : const char* buffer_;
65 : Semaphore* const free_space_;
66 : Semaphore* const used_space_;
67 : };
68 :
69 :
70 1 : class WaitAndSignalThread final : public Thread {
71 : public:
72 : explicit WaitAndSignalThread(Semaphore* semaphore)
73 2 : : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {}
74 :
75 2 : void Run() override {
76 402 : for (int n = 0; n < 100; ++n) {
77 200 : semaphore_->Wait();
78 400 : ASSERT_FALSE(semaphore_->WaitFor(TimeDelta::FromMicroseconds(1)));
79 200 : semaphore_->Signal();
80 : }
81 : }
82 :
83 : private:
84 : Semaphore* const semaphore_;
85 : };
86 :
87 : } // namespace
88 :
89 :
90 15443 : TEST(Semaphore, ProducerConsumer) {
91 : char buffer[kBufferSize];
92 : std::memset(buffer, 0, sizeof(buffer));
93 2 : Semaphore free_space(kBufferSize);
94 2 : Semaphore used_space(0);
95 : ProducerThread producer_thread(buffer, &free_space, &used_space);
96 : ConsumerThread consumer_thread(buffer, &free_space, &used_space);
97 1 : producer_thread.Start();
98 1 : consumer_thread.Start();
99 1 : producer_thread.Join();
100 1 : consumer_thread.Join();
101 1 : }
102 :
103 :
104 15443 : TEST(Semaphore, WaitAndSignal) {
105 2 : Semaphore semaphore(0);
106 : WaitAndSignalThread t1(&semaphore);
107 : WaitAndSignalThread t2(&semaphore);
108 :
109 1 : t1.Start();
110 1 : t2.Start();
111 :
112 : // Make something available.
113 1 : semaphore.Signal();
114 :
115 1 : t1.Join();
116 1 : t2.Join();
117 :
118 1 : semaphore.Wait();
119 :
120 2 : EXPECT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1)));
121 1 : }
122 :
123 :
124 15443 : TEST(Semaphore, WaitFor) {
125 2 : Semaphore semaphore(0);
126 :
127 : // Semaphore not signalled - timeout.
128 2 : ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
129 2 : ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
130 2 : ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
131 :
132 : // Semaphore signalled - no timeout.
133 1 : semaphore.Signal();
134 2 : ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
135 1 : semaphore.Signal();
136 2 : ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
137 1 : semaphore.Signal();
138 2 : ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
139 : }
140 :
141 : } // namespace base
142 9264 : } // namespace v8
|