blob: 5fbf320c82692cdc3604db175b9a462800b12f0a [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
2 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
jbauch555604a2016-04-26 10:13:2211#include <memory>
12
henrike@webrtc.orgf0488722014-05-13 18:00:2613#include "webrtc/base/common.h"
14#include "webrtc/base/gunit.h"
15#include "webrtc/base/messagehandler.h"
16#include "webrtc/base/messagequeue.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2617#include "webrtc/base/sharedexclusivelock.h"
18#include "webrtc/base/thread.h"
19#include "webrtc/base/timeutils.h"
20
terelius5262bac2016-04-26 15:55:3521#if defined(MEMORY_SANITIZER)
22// Flaky under MemorySanitizer, see
23// https://bugs.chromium.org/p/webrtc/issues/detail?id=5824
24#define MAYBE_TestSharedExclusive DISABLED_TestSharedExclusive
25#define MAYBE_TestExclusiveExclusive DISABLED_TestExclusiveExclusive
26#else
27#define MAYBE_TestSharedExclusive TestSharedExclusive
28#define MAYBE_TestExclusiveExclusive TestExclusiveExclusive
29#endif
30
henrike@webrtc.orgf0488722014-05-13 18:00:2631namespace rtc {
32
Peter Boström0c4e06b2015-10-07 10:23:2133static const uint32_t kMsgRead = 0;
34static const uint32_t kMsgWrite = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:2635static const int kNoWaitThresholdInMs = 10;
36static const int kWaitThresholdInMs = 80;
37static const int kProcessTimeInMs = 100;
38static const int kProcessTimeoutInMs = 5000;
39
40class SharedExclusiveTask : public MessageHandler {
41 public:
42 SharedExclusiveTask(SharedExclusiveLock* shared_exclusive_lock,
43 int* value,
44 bool* done)
45 : shared_exclusive_lock_(shared_exclusive_lock),
46 waiting_time_in_ms_(0),
47 value_(value),
48 done_(done) {
49 worker_thread_.reset(new Thread());
50 worker_thread_->Start();
51 }
52
Honghai Zhang82d78622016-05-06 18:29:1553 int64_t waiting_time_in_ms() const { return waiting_time_in_ms_; }
henrike@webrtc.orgf0488722014-05-13 18:00:2654
55 protected:
jbauch555604a2016-04-26 10:13:2256 std::unique_ptr<Thread> worker_thread_;
henrike@webrtc.orgf0488722014-05-13 18:00:2657 SharedExclusiveLock* shared_exclusive_lock_;
Honghai Zhang82d78622016-05-06 18:29:1558 int64_t waiting_time_in_ms_;
henrike@webrtc.orgf0488722014-05-13 18:00:2659 int* value_;
60 bool* done_;
61};
62
63class ReadTask : public SharedExclusiveTask {
64 public:
65 ReadTask(SharedExclusiveLock* shared_exclusive_lock, int* value, bool* done)
66 : SharedExclusiveTask(shared_exclusive_lock, value, done) {
67 }
68
69 void PostRead(int* value) {
Taylor Brandstetter5d97a9a2016-06-10 21:17:2770 worker_thread_->Post(RTC_FROM_HERE, this, kMsgRead,
71 new TypedMessageData<int*>(value));
henrike@webrtc.orgf0488722014-05-13 18:00:2672 }
73
74 private:
75 virtual void OnMessage(Message* message) {
76 ASSERT(rtc::Thread::Current() == worker_thread_.get());
77 ASSERT(message != NULL);
78 ASSERT(message->message_id == kMsgRead);
79
80 TypedMessageData<int*>* message_data =
81 static_cast<TypedMessageData<int*>*>(message->pdata);
82
Honghai Zhang82d78622016-05-06 18:29:1583 int64_t start_time = TimeMillis();
henrike@webrtc.orgf0488722014-05-13 18:00:2684 {
85 SharedScope ss(shared_exclusive_lock_);
Honghai Zhang82d78622016-05-06 18:29:1586 waiting_time_in_ms_ = TimeDiff(TimeMillis(), start_time);
henrike@webrtc.orgf0488722014-05-13 18:00:2687
88 Thread::SleepMs(kProcessTimeInMs);
89 *message_data->data() = *value_;
90 *done_ = true;
91 }
92 delete message->pdata;
93 message->pdata = NULL;
94 }
95};
96
97class WriteTask : public SharedExclusiveTask {
98 public:
99 WriteTask(SharedExclusiveLock* shared_exclusive_lock, int* value, bool* done)
100 : SharedExclusiveTask(shared_exclusive_lock, value, done) {
101 }
102
103 void PostWrite(int value) {
Taylor Brandstetter5d97a9a2016-06-10 21:17:27104 worker_thread_->Post(RTC_FROM_HERE, this, kMsgWrite,
105 new TypedMessageData<int>(value));
henrike@webrtc.orgf0488722014-05-13 18:00:26106 }
107
108 private:
109 virtual void OnMessage(Message* message) {
110 ASSERT(rtc::Thread::Current() == worker_thread_.get());
111 ASSERT(message != NULL);
112 ASSERT(message->message_id == kMsgWrite);
113
114 TypedMessageData<int>* message_data =
115 static_cast<TypedMessageData<int>*>(message->pdata);
116
Honghai Zhang82d78622016-05-06 18:29:15117 int64_t start_time = TimeMillis();
henrike@webrtc.orgf0488722014-05-13 18:00:26118 {
119 ExclusiveScope es(shared_exclusive_lock_);
Honghai Zhang82d78622016-05-06 18:29:15120 waiting_time_in_ms_ = TimeDiff(TimeMillis(), start_time);
henrike@webrtc.orgf0488722014-05-13 18:00:26121
122 Thread::SleepMs(kProcessTimeInMs);
123 *value_ = message_data->data();
124 *done_ = true;
125 }
126 delete message->pdata;
127 message->pdata = NULL;
128 }
129};
130
131// Unit test for SharedExclusiveLock.
132class SharedExclusiveLockTest
133 : public testing::Test {
134 public:
135 SharedExclusiveLockTest() : value_(0) {
136 }
137
138 virtual void SetUp() {
139 shared_exclusive_lock_.reset(new SharedExclusiveLock());
140 }
141
142 protected:
jbauch555604a2016-04-26 10:13:22143 std::unique_ptr<SharedExclusiveLock> shared_exclusive_lock_;
henrike@webrtc.orgf0488722014-05-13 18:00:26144 int value_;
145};
146
henrike@webrtc.orgcaa01b12014-05-29 15:53:39147// Flaky: https://code.google.com/p/webrtc/issues/detail?id=3318
henrike@webrtc.orgc732a3e2014-10-09 22:08:15148TEST_F(SharedExclusiveLockTest, TestSharedShared) {
henrike@webrtc.orgf0488722014-05-13 18:00:26149 int value0, value1;
150 bool done0, done1;
151 ReadTask reader0(shared_exclusive_lock_.get(), &value_, &done0);
152 ReadTask reader1(shared_exclusive_lock_.get(), &value_, &done1);
153
154 // Test shared locks can be shared without waiting.
155 {
156 SharedScope ss(shared_exclusive_lock_.get());
157 value_ = 1;
158 done0 = false;
159 done1 = false;
160 reader0.PostRead(&value0);
161 reader1.PostRead(&value1);
162 Thread::SleepMs(kProcessTimeInMs);
163 }
164
165 EXPECT_TRUE_WAIT(done0, kProcessTimeoutInMs);
166 EXPECT_EQ(1, value0);
167 EXPECT_LE(reader0.waiting_time_in_ms(), kNoWaitThresholdInMs);
168 EXPECT_TRUE_WAIT(done1, kProcessTimeoutInMs);
169 EXPECT_EQ(1, value1);
170 EXPECT_LE(reader1.waiting_time_in_ms(), kNoWaitThresholdInMs);
171}
172
terelius5262bac2016-04-26 15:55:35173TEST_F(SharedExclusiveLockTest, MAYBE_TestSharedExclusive) {
henrike@webrtc.orgf0488722014-05-13 18:00:26174 bool done;
175 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
176
177 // Test exclusive lock needs to wait for shared lock.
178 {
179 SharedScope ss(shared_exclusive_lock_.get());
180 value_ = 1;
181 done = false;
182 writer.PostWrite(2);
183 Thread::SleepMs(kProcessTimeInMs);
184 EXPECT_EQ(1, value_);
185 }
186
187 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
188 EXPECT_EQ(2, value_);
189 EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
190}
191
henrike@webrtc.orgc732a3e2014-10-09 22:08:15192TEST_F(SharedExclusiveLockTest, TestExclusiveShared) {
henrike@webrtc.orgf0488722014-05-13 18:00:26193 int value;
194 bool done;
195 ReadTask reader(shared_exclusive_lock_.get(), &value_, &done);
196
197 // Test shared lock needs to wait for exclusive lock.
198 {
199 ExclusiveScope es(shared_exclusive_lock_.get());
200 value_ = 1;
201 done = false;
202 reader.PostRead(&value);
203 Thread::SleepMs(kProcessTimeInMs);
204 value_ = 2;
205 }
206
207 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
208 EXPECT_EQ(2, value);
209 EXPECT_GE(reader.waiting_time_in_ms(), kWaitThresholdInMs);
210}
211
terelius5262bac2016-04-26 15:55:35212TEST_F(SharedExclusiveLockTest, MAYBE_TestExclusiveExclusive) {
henrike@webrtc.orgf0488722014-05-13 18:00:26213 bool done;
214 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
215
216 // Test exclusive lock needs to wait for exclusive lock.
217 {
218 ExclusiveScope es(shared_exclusive_lock_.get());
219 value_ = 1;
220 done = false;
221 writer.PostWrite(2);
222 Thread::SleepMs(kProcessTimeInMs);
223 EXPECT_EQ(1, value_);
224 }
225
226 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
227 EXPECT_EQ(2, value_);
228 EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
229}
230
231} // namespace rtc