blob: c124db5c82fe1895d44236f80823b498f282974b [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
11#include "webrtc/base/common.h"
12#include "webrtc/base/gunit.h"
13#include "webrtc/base/messagehandler.h"
14#include "webrtc/base/messagequeue.h"
15#include "webrtc/base/scoped_ptr.h"
16#include "webrtc/base/sharedexclusivelock.h"
17#include "webrtc/base/thread.h"
18#include "webrtc/base/timeutils.h"
henrike@webrtc.orgfded02c2014-09-19 13:10:10 +000019#include "webrtc/test/testsupport/gtest_disable.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000020
21namespace rtc {
22
23static const uint32 kMsgRead = 0;
24static const uint32 kMsgWrite = 0;
25static const int kNoWaitThresholdInMs = 10;
26static const int kWaitThresholdInMs = 80;
27static const int kProcessTimeInMs = 100;
28static const int kProcessTimeoutInMs = 5000;
29
30class SharedExclusiveTask : public MessageHandler {
31 public:
32 SharedExclusiveTask(SharedExclusiveLock* shared_exclusive_lock,
33 int* value,
34 bool* done)
35 : shared_exclusive_lock_(shared_exclusive_lock),
36 waiting_time_in_ms_(0),
37 value_(value),
38 done_(done) {
39 worker_thread_.reset(new Thread());
40 worker_thread_->Start();
41 }
42
43 int waiting_time_in_ms() const { return waiting_time_in_ms_; }
44
45 protected:
46 scoped_ptr<Thread> worker_thread_;
47 SharedExclusiveLock* shared_exclusive_lock_;
48 int waiting_time_in_ms_;
49 int* value_;
50 bool* done_;
51};
52
53class ReadTask : public SharedExclusiveTask {
54 public:
55 ReadTask(SharedExclusiveLock* shared_exclusive_lock, int* value, bool* done)
56 : SharedExclusiveTask(shared_exclusive_lock, value, done) {
57 }
58
59 void PostRead(int* value) {
60 worker_thread_->Post(this, kMsgRead, new TypedMessageData<int*>(value));
61 }
62
63 private:
64 virtual void OnMessage(Message* message) {
65 ASSERT(rtc::Thread::Current() == worker_thread_.get());
66 ASSERT(message != NULL);
67 ASSERT(message->message_id == kMsgRead);
68
69 TypedMessageData<int*>* message_data =
70 static_cast<TypedMessageData<int*>*>(message->pdata);
71
72 uint32 start_time = Time();
73 {
74 SharedScope ss(shared_exclusive_lock_);
75 waiting_time_in_ms_ = TimeDiff(Time(), start_time);
76
77 Thread::SleepMs(kProcessTimeInMs);
78 *message_data->data() = *value_;
79 *done_ = true;
80 }
81 delete message->pdata;
82 message->pdata = NULL;
83 }
84};
85
86class WriteTask : public SharedExclusiveTask {
87 public:
88 WriteTask(SharedExclusiveLock* shared_exclusive_lock, int* value, bool* done)
89 : SharedExclusiveTask(shared_exclusive_lock, value, done) {
90 }
91
92 void PostWrite(int value) {
93 worker_thread_->Post(this, kMsgWrite, new TypedMessageData<int>(value));
94 }
95
96 private:
97 virtual void OnMessage(Message* message) {
98 ASSERT(rtc::Thread::Current() == worker_thread_.get());
99 ASSERT(message != NULL);
100 ASSERT(message->message_id == kMsgWrite);
101
102 TypedMessageData<int>* message_data =
103 static_cast<TypedMessageData<int>*>(message->pdata);
104
105 uint32 start_time = Time();
106 {
107 ExclusiveScope es(shared_exclusive_lock_);
108 waiting_time_in_ms_ = TimeDiff(Time(), start_time);
109
110 Thread::SleepMs(kProcessTimeInMs);
111 *value_ = message_data->data();
112 *done_ = true;
113 }
114 delete message->pdata;
115 message->pdata = NULL;
116 }
117};
118
119// Unit test for SharedExclusiveLock.
120class SharedExclusiveLockTest
121 : public testing::Test {
122 public:
123 SharedExclusiveLockTest() : value_(0) {
124 }
125
126 virtual void SetUp() {
127 shared_exclusive_lock_.reset(new SharedExclusiveLock());
128 }
129
130 protected:
131 scoped_ptr<SharedExclusiveLock> shared_exclusive_lock_;
132 int value_;
133};
134
henrike@webrtc.orgcaa01b12014-05-29 15:53:39 +0000135// Flaky: https://code.google.com/p/webrtc/issues/detail?id=3318
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000136TEST_F(SharedExclusiveLockTest, TestSharedShared) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000137 int value0, value1;
138 bool done0, done1;
139 ReadTask reader0(shared_exclusive_lock_.get(), &value_, &done0);
140 ReadTask reader1(shared_exclusive_lock_.get(), &value_, &done1);
141
142 // Test shared locks can be shared without waiting.
143 {
144 SharedScope ss(shared_exclusive_lock_.get());
145 value_ = 1;
146 done0 = false;
147 done1 = false;
148 reader0.PostRead(&value0);
149 reader1.PostRead(&value1);
150 Thread::SleepMs(kProcessTimeInMs);
151 }
152
153 EXPECT_TRUE_WAIT(done0, kProcessTimeoutInMs);
154 EXPECT_EQ(1, value0);
155 EXPECT_LE(reader0.waiting_time_in_ms(), kNoWaitThresholdInMs);
156 EXPECT_TRUE_WAIT(done1, kProcessTimeoutInMs);
157 EXPECT_EQ(1, value1);
158 EXPECT_LE(reader1.waiting_time_in_ms(), kNoWaitThresholdInMs);
159}
160
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000161TEST_F(SharedExclusiveLockTest, TestSharedExclusive) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000162 bool done;
163 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
164
165 // Test exclusive lock needs to wait for shared lock.
166 {
167 SharedScope ss(shared_exclusive_lock_.get());
168 value_ = 1;
169 done = false;
170 writer.PostWrite(2);
171 Thread::SleepMs(kProcessTimeInMs);
172 EXPECT_EQ(1, value_);
173 }
174
175 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
176 EXPECT_EQ(2, value_);
177 EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
178}
179
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000180TEST_F(SharedExclusiveLockTest, TestExclusiveShared) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000181 int value;
182 bool done;
183 ReadTask reader(shared_exclusive_lock_.get(), &value_, &done);
184
185 // Test shared lock needs to wait for exclusive lock.
186 {
187 ExclusiveScope es(shared_exclusive_lock_.get());
188 value_ = 1;
189 done = false;
190 reader.PostRead(&value);
191 Thread::SleepMs(kProcessTimeInMs);
192 value_ = 2;
193 }
194
195 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
196 EXPECT_EQ(2, value);
197 EXPECT_GE(reader.waiting_time_in_ms(), kWaitThresholdInMs);
198}
199
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000200TEST_F(SharedExclusiveLockTest, TestExclusiveExclusive) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000201 bool done;
202 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
203
204 // Test exclusive lock needs to wait for exclusive lock.
205 {
206 ExclusiveScope es(shared_exclusive_lock_.get());
207 value_ = 1;
208 done = false;
209 writer.PostWrite(2);
210 Thread::SleepMs(kProcessTimeInMs);
211 EXPECT_EQ(1, value_);
212 }
213
214 EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
215 EXPECT_EQ(2, value_);
216 EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
217}
218
219} // namespace rtc