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 class ProducerThread final : public Thread {
24 public:
ProducerThread(char * buffer,Semaphore * free_space,Semaphore * used_space)25 ProducerThread(char* buffer, Semaphore* free_space, Semaphore* used_space)
26 : Thread(Options("ProducerThread")),
27 buffer_(buffer),
28 free_space_(free_space),
29 used_space_(used_space) {}
30
Run()31 void Run() override {
32 for (size_t n = 0; n < kDataSize; ++n) {
33 free_space_->Wait();
34 buffer_[n % kBufferSize] = kAlphabet[n % kAlphabetSize];
35 used_space_->Signal();
36 }
37 }
38
39 private:
40 char* buffer_;
41 Semaphore* const free_space_;
42 Semaphore* const used_space_;
43 };
44
45
46 class ConsumerThread final : public Thread {
47 public:
ConsumerThread(const char * buffer,Semaphore * free_space,Semaphore * used_space)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 used_space_(used_space) {}
54
Run()55 void Run() override {
56 for (size_t n = 0; n < kDataSize; ++n) {
57 used_space_->Wait();
58 EXPECT_EQ(kAlphabet[n % kAlphabetSize], buffer_[n % kBufferSize]);
59 free_space_->Signal();
60 }
61 }
62
63 private:
64 const char* buffer_;
65 Semaphore* const free_space_;
66 Semaphore* const used_space_;
67 };
68
69
70 class WaitAndSignalThread final : public Thread {
71 public:
WaitAndSignalThread(Semaphore * semaphore)72 explicit WaitAndSignalThread(Semaphore* semaphore)
73 : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {}
74
Run()75 void Run() override {
76 for (int n = 0; n < 100; ++n) {
77 semaphore_->Wait();
78 ASSERT_FALSE(semaphore_->WaitFor(TimeDelta::FromMicroseconds(1)));
79 semaphore_->Signal();
80 }
81 }
82
83 private:
84 Semaphore* const semaphore_;
85 };
86
87 } // namespace
88
89
TEST(Semaphore,ProducerConsumer)90 TEST(Semaphore, ProducerConsumer) {
91 char buffer[kBufferSize];
92 std::memset(buffer, 0, sizeof(buffer));
93 Semaphore free_space(kBufferSize);
94 Semaphore used_space(0);
95 ProducerThread producer_thread(buffer, &free_space, &used_space);
96 ConsumerThread consumer_thread(buffer, &free_space, &used_space);
97 producer_thread.Start();
98 consumer_thread.Start();
99 producer_thread.Join();
100 consumer_thread.Join();
101 }
102
103
TEST(Semaphore,WaitAndSignal)104 TEST(Semaphore, WaitAndSignal) {
105 Semaphore semaphore(0);
106 WaitAndSignalThread t1(&semaphore);
107 WaitAndSignalThread t2(&semaphore);
108
109 t1.Start();
110 t2.Start();
111
112 // Make something available.
113 semaphore.Signal();
114
115 t1.Join();
116 t2.Join();
117
118 semaphore.Wait();
119
120 EXPECT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1)));
121 }
122
123
TEST(Semaphore,WaitFor)124 TEST(Semaphore, WaitFor) {
125 Semaphore semaphore(0);
126
127 // Semaphore not signalled - timeout.
128 ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
129 ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
130 ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
131
132 // Semaphore signalled - no timeout.
133 semaphore.Signal();
134 ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
135 semaphore.Signal();
136 ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
137 semaphore.Signal();
138 ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
139 }
140
141 } // namespace base
142 } // namespace v8
143