blob: 45902af39e662d7426fb2fce6da0ce15a57987b3 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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 03:13:22 -070011#include <memory>
12
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013#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:26 +000017#include "webrtc/base/sharedexclusivelock.h"
18#include "webrtc/base/thread.h"
19#include "webrtc/base/timeutils.h"
20
terelius5262bac2016-04-26 08:55:35 -070021#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:26 +000031namespace rtc {
32
Peter Boström0c4e06b2015-10-07 12:23:21 +020033static const uint32_t kMsgRead = 0;
34static const uint32_t kMsgWrite = 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000035static 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 11:29:15 -070053 int64_t waiting_time_in_ms() const { return waiting_time_in_ms_; }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000054
55 protected:
jbauch555604a2016-04-26 03:13:22 -070056 std::unique_ptr<Thread> worker_thread_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000057 SharedExclusiveLock* shared_exclusive_lock_;
Honghai Zhang82d78622016-05-06 11:29:15 -070058 int64_t waiting_time_in_ms_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000059 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) {
70 worker_thread_->Post(this, kMsgRead, new TypedMessageData<int*>(value));
71 }
72
73 private:
74 virtual void OnMessage(Message* message) {
75 ASSERT(rtc::Thread::Current() == worker_thread_.get());
76 ASSERT(message != NULL);
77 ASSERT(message->message_id == kMsgRead);
78
79 TypedMessageData<int*>* message_data =
80 static_cast<TypedMessageData<int*>*>(message->pdata);
81
Honghai Zhang82d78622016-05-06 11:29:15 -070082 int64_t start_time = TimeMillis();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000083 {
84 SharedScope ss(shared_exclusive_lock_);
Honghai Zhang82d78622016-05-06 11:29:15 -070085 waiting_time_in_ms_ = TimeDiff(TimeMillis(), start_time);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000086
87 Thread::SleepMs(kProcessTimeInMs);
88 *message_data->data() = *value_;
89 *done_ = true;
90 }
91 delete message->pdata;
92 message->pdata = NULL;
93 }
94};
95
96class WriteTask : public SharedExclusiveTask {
97 public:
98 WriteTask(SharedExclusiveLock* shared_exclusive_lock, int* value, bool* done)
99 : SharedExclusiveTask(shared_exclusive_lock, value, done) {
100 }
101
102 void PostWrite(int value) {
103 worker_thread_->Post(this, kMsgWrite, new TypedMessageData<int>(value));
104 }
105
106 private:
107 virtual void OnMessage(Message* message) {
108 ASSERT(rtc::Thread::Current() == worker_thread_.get());
109 ASSERT(message != NULL);
110 ASSERT(message->message_id == kMsgWrite);
111
112 TypedMessageData<int>* message_data =
113 static_cast<TypedMessageData<int>*>(message->pdata);
114
Honghai Zhang82d78622016-05-06 11:29:15 -0700115 int64_t start_time = TimeMillis();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116 {
117 ExclusiveScope es(shared_exclusive_lock_);
Honghai Zhang82d78622016-05-06 11:29:15 -0700118 waiting_time_in_ms_ = TimeDiff(TimeMillis(), start_time);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000119
120 Thread::SleepMs(kProcessTimeInMs);
121 *value_ = message_data->data();
122 *done_ = true;
123 }
124 delete message->pdata;
125 message->pdata = NULL;
126 }
127};
128
129// Unit test for SharedExclusiveLock.
130class SharedExclusiveLockTest
131 : public testing::Test {
132 public:
133 SharedExclusiveLockTest() : value_(0) {
134 }
135
136 virtual void SetUp() {
137 shared_exclusive_lock_.reset(new SharedExclusiveLock());
138 }
139
140 protected:
jbauch555604a2016-04-26 03:13:22 -0700141 std::unique_ptr<SharedExclusiveLock> shared_exclusive_lock_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000142 int value_;
143};
144
henrike@webrtc.orgcaa01b12014-05-29 15:53:39 +0000145// Flaky: https://code.google.com/p/webrtc/issues/detail?id=3318
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000146TEST_F(SharedExclusiveLockTest, TestSharedShared) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000147 int value0, value1;
148 bool done0, done1;
149 ReadTask reader0(shared_exclusive_lock_.get(), &value_, &done0);
150 ReadTask reader1(shared_exclusive_lock_.get(), &value_, &done1);
151
152 // Test shared locks can be shared without waiting.
153 {
154 SharedScope ss(shared_exclusive_lock_.get());
155 value_ = 1;
156 done0 = false;
157 done1 = false;
158 reader0.PostRead(&value0);
159 reader1.PostRead(&value1);
160 Thread::SleepMs(kProcessTimeInMs);
161 }
162
163 EXPECT_TRUE_WAIT(done0, kProcessTimeoutInMs);
164 EXPECT_EQ(1, value0);
165 EXPECT_LE(reader0.waiting_time_in_ms(), kNoWaitThresholdInMs);
166 EXPECT_TRUE_WAIT(done1, kProcessTimeoutInMs);
167 EXPECT_EQ(1, value1);
168 EXPECT_LE(reader1.waiting_time_in_ms(), kNoWaitThresholdInMs);
169}
170
terelius5262bac2016-04-26 08:55:35 -0700171TEST_F(SharedExclusiveLockTest, MAYBE_TestSharedExclusive) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000172 bool done;
173 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
174
175 // Test exclusive lock needs to wait for shared lock.
176 {
177 SharedScope ss(shared_exclusive_lock_.get());
178 value_ = 1;
179 done = false;
180 writer.PostWrite(2);
181 Thread::SleepMs(kProcessTimeInMs);
182 EXPECT_EQ(1, value_);
183 }
184
185 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
186 EXPECT_EQ(2, value_);
187 EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
188}
189
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000190TEST_F(SharedExclusiveLockTest, TestExclusiveShared) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000191 int value;
192 bool done;
193 ReadTask reader(shared_exclusive_lock_.get(), &value_, &done);
194
195 // Test shared lock needs to wait for exclusive lock.
196 {
197 ExclusiveScope es(shared_exclusive_lock_.get());
198 value_ = 1;
199 done = false;
200 reader.PostRead(&value);
201 Thread::SleepMs(kProcessTimeInMs);
202 value_ = 2;
203 }
204
205 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
206 EXPECT_EQ(2, value);
207 EXPECT_GE(reader.waiting_time_in_ms(), kWaitThresholdInMs);
208}
209
terelius5262bac2016-04-26 08:55:35 -0700210TEST_F(SharedExclusiveLockTest, MAYBE_TestExclusiveExclusive) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000211 bool done;
212 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
213
214 // Test exclusive lock needs to wait for exclusive lock.
215 {
216 ExclusiveScope es(shared_exclusive_lock_.get());
217 value_ = 1;
218 done = false;
219 writer.PostWrite(2);
220 Thread::SleepMs(kProcessTimeInMs);
221 EXPECT_EQ(1, value_);
222 }
223
224 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
225 EXPECT_EQ(2, value_);
226 EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
227}
228
229} // namespace rtc