Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 V8_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 virtual ~ProducerThread() {} | |
| 31 | |
| 32 virtual void Run() V8_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 V8_FINAL : public Thread { | |
| 48 public: | |
| 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) {} | |
| 55 virtual ~ConsumerThread() {} | |
| 56 | |
| 57 virtual void Run() V8_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 V8_FINAL : public Thread { | |
| 73 public: | |
| 74 explicit WaitAndSignalThread(Semaphore* semaphore) | |
| 75 : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {} | |
| 76 virtual ~WaitAndSignalThread() {} | |
| 77 | |
| 78 virtual void Run() V8_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 | |
| 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 | |
| 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))); | |
|
Michael Achenbach
2014/08/22 08:21:07
What's the difference to ASSERT_FALSE above?
Benedikt Meurer
2014/08/22 08:51:58
EXPECT_* just record a failure, while ASSERT_* ter
| |
| 124 } | |
| 125 | |
| 126 | |
| 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))); | |
|
Michael Achenbach
2014/08/22 08:21:07
Do we really need the last one? What could make th
| |
| 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 | |
| OLD | NEW |