Fix data races in ThreadTest.ThreeThreadsInvoke.

R=henrike@webrtc.org
BUG=

Review URL: https://webrtc-codereview.appspot.com/26819004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7457 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org 2014-10-15 14:54:56 +00:00
parent f87c0aff7f
commit e93cbd13d5
2 changed files with 32 additions and 11 deletions

View File

@ -313,42 +313,64 @@ TEST(ThreadTest, ThreeThreadsInvoke) {
thread_b.Start();
thread_c.Start();
class LockedBool {
public:
explicit LockedBool(bool value) : value_(value) {}
void Set(bool value) {
CritScope lock(&crit_);
value_ = value;
}
bool Get() {
CritScope lock(&crit_);
return value_;
}
private:
CriticalSection crit_;
bool value_ GUARDED_BY(crit_);
};
struct LocalFuncs {
static void Set(bool* out) { *out = true; }
static void InvokeSet(Thread* thread, bool* out) {
static void Set(LockedBool* out) { out->Set(true); }
static void InvokeSet(Thread* thread, LockedBool* out) {
thread->Invoke<void>(Bind(&Set, out));
}
// Set |out| true and call InvokeSet on |thread|.
static void SetAndInvokeSet(bool* out, Thread* thread, bool* out_inner) {
*out = true;
static void SetAndInvokeSet(LockedBool* out,
Thread* thread,
LockedBool* out_inner) {
out->Set(true);
InvokeSet(thread, out_inner);
}
// Asynchronously invoke SetAndInvokeSet on |thread1| and wait until
// |thread1| starts the call.
static void AsyncInvokeSetAndWait(
Thread* thread1, Thread* thread2, bool* out) {
bool async_invoked = false;
Thread* thread1, Thread* thread2, LockedBool* out) {
CriticalSection crit;
LockedBool async_invoked(false);
AsyncInvoker invoker;
invoker.AsyncInvoke<void>(
thread1, Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
EXPECT_TRUE_WAIT(async_invoked, 2000);
EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
}
};
bool thread_a_called = false;
LockedBool thread_a_called(false);
// Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
// Thread B returns when C receives the call and C should be blocked until A
// starts to process messages.
thread_b.Invoke<void>(Bind(&LocalFuncs::AsyncInvokeSetAndWait,
&thread_c, thread_a, &thread_a_called));
EXPECT_FALSE(thread_a_called);
EXPECT_FALSE(thread_a_called.Get());
EXPECT_TRUE_WAIT(thread_a_called, 2000);
EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
}
class AsyncInvokeTest : public testing::Test {

View File

@ -44,7 +44,6 @@ char kTSanDefaultSuppressions[] =
// rtc_unittest
// https://code.google.com/p/webrtc/issues/detail?id=3911 for details.
"race:ThreadTest_ThreeThreadsInvoke_Test::TestBody()::LocalFuncs::SetAndInvokeSet\n"
"race:rtc::FireAndForgetAsyncClosure<FunctorB>::Execute\n"
"race:rtc::MessageQueueManager::Clear\n"
"race:rtc::Thread::Clear\n"