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