blob: 3886fb27ab1a0771f7f091cc6777ae407b7fb36d [file] [log] [blame]
henrike@webrtc.org47be73b2014-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
jbauch1286d0e2016-04-26 10:13:2211#include <memory>
12
henrike@webrtc.org47be73b2014-05-13 18:00:2613#include "webrtc/base/common.h"
14#include "webrtc/base/gunit.h"
skvladb94713a2016-10-05 22:58:1215#include "webrtc/base/event.h"
henrike@webrtc.org47be73b2014-05-13 18:00:2616#include "webrtc/base/messagehandler.h"
17#include "webrtc/base/messagequeue.h"
henrike@webrtc.org47be73b2014-05-13 18:00:2618#include "webrtc/base/sharedexclusivelock.h"
19#include "webrtc/base/thread.h"
20#include "webrtc/base/timeutils.h"
henrike@webrtc.org47be73b2014-05-13 18:00:2621
henrike@webrtc.org47be73b2014-05-13 18:00:2622namespace rtc {
23
Peter Boström07e22e62015-10-07 10:23:2124static const uint32_t kMsgRead = 0;
25static const uint32_t kMsgWrite = 0;
henrike@webrtc.org47be73b2014-05-13 18:00:2626static const int kNoWaitThresholdInMs = 10;
27static const int kWaitThresholdInMs = 80;
28static const int kProcessTimeInMs = 100;
29static const int kProcessTimeoutInMs = 5000;
30
31class SharedExclusiveTask : public MessageHandler {
32 public:
33 SharedExclusiveTask(SharedExclusiveLock* shared_exclusive_lock,
34 int* value,
skvladb94713a2016-10-05 22:58:1235 Event* done)
henrike@webrtc.org47be73b2014-05-13 18:00:2636 : shared_exclusive_lock_(shared_exclusive_lock),
henrike@webrtc.org47be73b2014-05-13 18:00:2637 value_(value),
38 done_(done) {
39 worker_thread_.reset(new Thread());
40 worker_thread_->Start();
41 }
42
henrike@webrtc.org47be73b2014-05-13 18:00:2643 protected:
jbauch1286d0e2016-04-26 10:13:2244 std::unique_ptr<Thread> worker_thread_;
henrike@webrtc.org47be73b2014-05-13 18:00:2645 SharedExclusiveLock* shared_exclusive_lock_;
henrike@webrtc.org47be73b2014-05-13 18:00:2646 int* value_;
skvladb94713a2016-10-05 22:58:1247 Event* done_;
henrike@webrtc.org47be73b2014-05-13 18:00:2648};
49
50class ReadTask : public SharedExclusiveTask {
51 public:
skvladb94713a2016-10-05 22:58:1252 ReadTask(SharedExclusiveLock* shared_exclusive_lock, int* value, Event* done)
henrike@webrtc.org47be73b2014-05-13 18:00:2653 : SharedExclusiveTask(shared_exclusive_lock, value, done) {
54 }
55
56 void PostRead(int* value) {
Taylor Brandstetterc0bec8f2016-06-10 21:17:2757 worker_thread_->Post(RTC_FROM_HERE, this, kMsgRead,
58 new TypedMessageData<int*>(value));
henrike@webrtc.org47be73b2014-05-13 18:00:2659 }
60
61 private:
62 virtual void OnMessage(Message* message) {
63 ASSERT(rtc::Thread::Current() == worker_thread_.get());
64 ASSERT(message != NULL);
65 ASSERT(message->message_id == kMsgRead);
66
67 TypedMessageData<int*>* message_data =
68 static_cast<TypedMessageData<int*>*>(message->pdata);
69
henrike@webrtc.org47be73b2014-05-13 18:00:2670 {
71 SharedScope ss(shared_exclusive_lock_);
henrike@webrtc.org47be73b2014-05-13 18:00:2672 *message_data->data() = *value_;
skvladb94713a2016-10-05 22:58:1273 done_->Set();
henrike@webrtc.org47be73b2014-05-13 18:00:2674 }
75 delete message->pdata;
76 message->pdata = NULL;
77 }
78};
79
80class WriteTask : public SharedExclusiveTask {
81 public:
skvladb94713a2016-10-05 22:58:1282 WriteTask(SharedExclusiveLock* shared_exclusive_lock, int* value, Event* done)
henrike@webrtc.org47be73b2014-05-13 18:00:2683 : SharedExclusiveTask(shared_exclusive_lock, value, done) {
84 }
85
86 void PostWrite(int value) {
Taylor Brandstetterc0bec8f2016-06-10 21:17:2787 worker_thread_->Post(RTC_FROM_HERE, this, kMsgWrite,
88 new TypedMessageData<int>(value));
henrike@webrtc.org47be73b2014-05-13 18:00:2689 }
90
91 private:
92 virtual void OnMessage(Message* message) {
93 ASSERT(rtc::Thread::Current() == worker_thread_.get());
94 ASSERT(message != NULL);
95 ASSERT(message->message_id == kMsgWrite);
96
97 TypedMessageData<int>* message_data =
98 static_cast<TypedMessageData<int>*>(message->pdata);
99
henrike@webrtc.org47be73b2014-05-13 18:00:26100 {
101 ExclusiveScope es(shared_exclusive_lock_);
henrike@webrtc.org47be73b2014-05-13 18:00:26102 *value_ = message_data->data();
skvladb94713a2016-10-05 22:58:12103 done_->Set();
henrike@webrtc.org47be73b2014-05-13 18:00:26104 }
105 delete message->pdata;
106 message->pdata = NULL;
107 }
108};
109
110// Unit test for SharedExclusiveLock.
111class SharedExclusiveLockTest
112 : public testing::Test {
113 public:
114 SharedExclusiveLockTest() : value_(0) {
115 }
116
117 virtual void SetUp() {
118 shared_exclusive_lock_.reset(new SharedExclusiveLock());
119 }
120
121 protected:
jbauch1286d0e2016-04-26 10:13:22122 std::unique_ptr<SharedExclusiveLock> shared_exclusive_lock_;
henrike@webrtc.org47be73b2014-05-13 18:00:26123 int value_;
124};
125
henrike@webrtc.orgd0892c42014-10-09 22:08:15126TEST_F(SharedExclusiveLockTest, TestSharedShared) {
henrike@webrtc.org47be73b2014-05-13 18:00:26127 int value0, value1;
skvladb94713a2016-10-05 22:58:12128 Event done0(false, false), done1(false, false);
henrike@webrtc.org47be73b2014-05-13 18:00:26129 ReadTask reader0(shared_exclusive_lock_.get(), &value_, &done0);
130 ReadTask reader1(shared_exclusive_lock_.get(), &value_, &done1);
131
132 // Test shared locks can be shared without waiting.
133 {
134 SharedScope ss(shared_exclusive_lock_.get());
135 value_ = 1;
henrike@webrtc.org47be73b2014-05-13 18:00:26136 reader0.PostRead(&value0);
137 reader1.PostRead(&value1);
henrike@webrtc.org47be73b2014-05-13 18:00:26138
skvladb94713a2016-10-05 22:58:12139 EXPECT_TRUE(done0.Wait(kProcessTimeoutInMs));
140 EXPECT_TRUE(done1.Wait(kProcessTimeoutInMs));
141 EXPECT_EQ(1, value0);
142 EXPECT_EQ(1, value1);
143 }
henrike@webrtc.org47be73b2014-05-13 18:00:26144}
145
skvladb94713a2016-10-05 22:58:12146TEST_F(SharedExclusiveLockTest, TestSharedExclusive) {
147 Event done(false, false);
henrike@webrtc.org47be73b2014-05-13 18:00:26148 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
149
150 // Test exclusive lock needs to wait for shared lock.
151 {
152 SharedScope ss(shared_exclusive_lock_.get());
153 value_ = 1;
henrike@webrtc.org47be73b2014-05-13 18:00:26154 writer.PostWrite(2);
skvladb94713a2016-10-05 22:58:12155 EXPECT_FALSE(done.Wait(kProcessTimeInMs));
henrike@webrtc.org47be73b2014-05-13 18:00:26156 }
skvladb94713a2016-10-05 22:58:12157 EXPECT_TRUE(done.Wait(kProcessTimeoutInMs));
henrike@webrtc.org47be73b2014-05-13 18:00:26158 EXPECT_EQ(2, value_);
henrike@webrtc.org47be73b2014-05-13 18:00:26159}
160
henrike@webrtc.orgd0892c42014-10-09 22:08:15161TEST_F(SharedExclusiveLockTest, TestExclusiveShared) {
henrike@webrtc.org47be73b2014-05-13 18:00:26162 int value;
skvladb94713a2016-10-05 22:58:12163 Event done(false, false);
henrike@webrtc.org47be73b2014-05-13 18:00:26164 ReadTask reader(shared_exclusive_lock_.get(), &value_, &done);
165
166 // Test shared lock needs to wait for exclusive lock.
167 {
168 ExclusiveScope es(shared_exclusive_lock_.get());
169 value_ = 1;
henrike@webrtc.org47be73b2014-05-13 18:00:26170 reader.PostRead(&value);
skvladb94713a2016-10-05 22:58:12171 EXPECT_FALSE(done.Wait(kProcessTimeInMs));
henrike@webrtc.org47be73b2014-05-13 18:00:26172 value_ = 2;
173 }
174
skvladb94713a2016-10-05 22:58:12175 EXPECT_TRUE(done.Wait(kProcessTimeoutInMs));
henrike@webrtc.org47be73b2014-05-13 18:00:26176 EXPECT_EQ(2, value);
henrike@webrtc.org47be73b2014-05-13 18:00:26177}
178
skvladb94713a2016-10-05 22:58:12179TEST_F(SharedExclusiveLockTest, TestExclusiveExclusive) {
180 Event done(false, false);
henrike@webrtc.org47be73b2014-05-13 18:00:26181 WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
182
183 // Test exclusive lock needs to wait for exclusive lock.
184 {
185 ExclusiveScope es(shared_exclusive_lock_.get());
skvladb94713a2016-10-05 22:58:12186 // Start the writer task only after holding the lock, to ensure it need
henrike@webrtc.org47be73b2014-05-13 18:00:26187 value_ = 1;
henrike@webrtc.org47be73b2014-05-13 18:00:26188 writer.PostWrite(2);
skvladb94713a2016-10-05 22:58:12189 EXPECT_FALSE(done.Wait(kProcessTimeInMs));
henrike@webrtc.org47be73b2014-05-13 18:00:26190 EXPECT_EQ(1, value_);
191 }
192
skvladb94713a2016-10-05 22:58:12193 EXPECT_TRUE(done.Wait(kProcessTimeoutInMs));
henrike@webrtc.org47be73b2014-05-13 18:00:26194 EXPECT_EQ(2, value_);
henrike@webrtc.org47be73b2014-05-13 18:00:26195}
196
197} // namespace rtc