OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/synchronization/atomic_flag.h" | 5 #include "base/synchronization/atomic_flag.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/single_thread_task_runner.h" | 9 #include "base/single_thread_task_runner.h" |
10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 // |expected_after_flag| is used to confirm that sequential consistency is | 61 // |expected_after_flag| is used to confirm that sequential consistency is |
62 // obtained around |tested_flag|. | 62 // obtained around |tested_flag|. |
63 bool expected_after_flag = false; | 63 bool expected_after_flag = false; |
64 // |reset_flag| is used to confirm the test flows as intended without using | 64 // |reset_flag| is used to confirm the test flows as intended without using |
65 // synchronization constructs which would defeat the purpose of exercising | 65 // synchronization constructs which would defeat the purpose of exercising |
66 // atomics. | 66 // atomics. |
67 AtomicFlag reset_flag; | 67 AtomicFlag reset_flag; |
68 | 68 |
69 Thread thread("AtomicFlagTest.ReadFromDifferentThread"); | 69 Thread thread("AtomicFlagTest.ReadFromDifferentThread"); |
70 ASSERT_TRUE(thread.Start()); | 70 ASSERT_TRUE(thread.Start()); |
71 thread.task_runner()->PostTask( | 71 thread.task_runner()->PostTask(FROM_HERE, |
72 FROM_HERE, | 72 BindOnce(&BusyWaitUntilFlagIsSet, &tested_flag, |
73 Bind(&BusyWaitUntilFlagIsSet, &tested_flag, &expected_after_flag, | 73 &expected_after_flag, &reset_flag)); |
74 &reset_flag)); | |
75 | 74 |
76 // To verify that IsSet() fetches the flag's value from memory every time it | 75 // To verify that IsSet() fetches the flag's value from memory every time it |
77 // is called (not just the first time that it is called on a thread), sleep | 76 // is called (not just the first time that it is called on a thread), sleep |
78 // before setting the flag. | 77 // before setting the flag. |
79 PlatformThread::Sleep(TimeDelta::FromMilliseconds(20)); | 78 PlatformThread::Sleep(TimeDelta::FromMilliseconds(20)); |
80 | 79 |
81 // |expected_after_flag| is used to verify that all memory operations | 80 // |expected_after_flag| is used to verify that all memory operations |
82 // performed before |tested_flag| is Set() are visible to threads that can see | 81 // performed before |tested_flag| is Set() are visible to threads that can see |
83 // IsSet(). | 82 // IsSet(). |
84 expected_after_flag = true; | 83 expected_after_flag = true; |
85 tested_flag.Set(); | 84 tested_flag.Set(); |
86 | 85 |
87 // Sleep again to give the busy loop time to observe the flag and verify | 86 // Sleep again to give the busy loop time to observe the flag and verify |
88 // expectations. | 87 // expectations. |
89 PlatformThread::Sleep(TimeDelta::FromMilliseconds(20)); | 88 PlatformThread::Sleep(TimeDelta::FromMilliseconds(20)); |
90 | 89 |
91 // Use |reset_flag| to confirm that the above completed (which the rest of | 90 // Use |reset_flag| to confirm that the above completed (which the rest of |
92 // this test assumes). | 91 // this test assumes). |
93 ASSERT_TRUE(reset_flag.IsSet()); | 92 ASSERT_TRUE(reset_flag.IsSet()); |
94 | 93 |
95 tested_flag.UnsafeResetForTesting(); | 94 tested_flag.UnsafeResetForTesting(); |
96 EXPECT_FALSE(tested_flag.IsSet()); | 95 EXPECT_FALSE(tested_flag.IsSet()); |
97 expected_after_flag = false; | 96 expected_after_flag = false; |
98 | 97 |
99 // Perform the same test again after the controlled UnsafeResetForTesting(), | 98 // Perform the same test again after the controlled UnsafeResetForTesting(), |
100 // |thread| is guaranteed to be synchronized past the | 99 // |thread| is guaranteed to be synchronized past the |
101 // |UnsafeResetForTesting()| call when the task runs per the implicit | 100 // |UnsafeResetForTesting()| call when the task runs per the implicit |
102 // synchronization in the post task mechanism. | 101 // synchronization in the post task mechanism. |
103 thread.task_runner()->PostTask( | 102 thread.task_runner()->PostTask(FROM_HERE, |
104 FROM_HERE, | 103 BindOnce(&BusyWaitUntilFlagIsSet, &tested_flag, |
105 Bind(&BusyWaitUntilFlagIsSet, &tested_flag, &expected_after_flag, | 104 &expected_after_flag, nullptr)); |
106 nullptr)); | |
107 | 105 |
108 PlatformThread::Sleep(TimeDelta::FromMilliseconds(20)); | 106 PlatformThread::Sleep(TimeDelta::FromMilliseconds(20)); |
109 | 107 |
110 expected_after_flag = true; | 108 expected_after_flag = true; |
111 tested_flag.Set(); | 109 tested_flag.Set(); |
112 | 110 |
113 // The |thread|'s destructor will block until the posted task completes, so | 111 // The |thread|'s destructor will block until the posted task completes, so |
114 // the test will time out if it fails to see the flag be set. | 112 // the test will time out if it fails to see the flag be set. |
115 } | 113 } |
116 | 114 |
117 TEST(AtomicFlagTest, SetOnDifferentSequenceDeathTest) { | 115 TEST(AtomicFlagTest, SetOnDifferentSequenceDeathTest) { |
118 // Checks that Set() can't be called from another sequence after being called | 116 // Checks that Set() can't be called from another sequence after being called |
119 // on this one. AtomicFlag should die on a DCHECK if Set() is called again | 117 // on this one. AtomicFlag should die on a DCHECK if Set() is called again |
120 // from another sequence. | 118 // from another sequence. |
121 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 119 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
122 Thread t("AtomicFlagTest.SetOnDifferentThreadDeathTest"); | 120 Thread t("AtomicFlagTest.SetOnDifferentThreadDeathTest"); |
123 ASSERT_TRUE(t.Start()); | 121 ASSERT_TRUE(t.Start()); |
124 EXPECT_TRUE(t.WaitUntilThreadStarted()); | 122 EXPECT_TRUE(t.WaitUntilThreadStarted()); |
125 | 123 |
126 AtomicFlag flag; | 124 AtomicFlag flag; |
127 flag.Set(); | 125 flag.Set(); |
128 t.task_runner()->PostTask(FROM_HERE, Bind(&ExpectSetFlagDeath, &flag)); | 126 t.task_runner()->PostTask(FROM_HERE, BindOnce(&ExpectSetFlagDeath, &flag)); |
129 } | 127 } |
130 | 128 |
131 } // namespace base | 129 } // namespace base |
OLD | NEW |