Home | History | Annotate | Download | only in platform
      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:
     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 
     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:
     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 
     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:
     72   explicit WaitAndSignalThread(Semaphore* semaphore)
     73       : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {}
     74 
     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 
     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 
    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 
    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