OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a | 5 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a |
6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to | 6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to |
7 // increase tolerance and reduce observed flakiness (though doing so reduces the | 7 // increase tolerance and reduce observed flakiness (though doing so reduces the |
8 // meaningfulness of the test). | 8 // meaningfulness of the test). |
9 | 9 |
10 #include "mojo/system/waiter_list.h" | 10 #include "mojo/system/waiter_list.h" |
11 | 11 |
12 #include "base/threading/platform_thread.h" // For |Sleep()|. | 12 #include "base/threading/platform_thread.h" // For |Sleep()|. |
13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 14 #include "mojo/system/handle_signals_state.h" |
14 #include "mojo/system/test_utils.h" | 15 #include "mojo/system/test_utils.h" |
15 #include "mojo/system/wait_flags_state.h" | |
16 #include "mojo/system/waiter.h" | 16 #include "mojo/system/waiter.h" |
17 #include "mojo/system/waiter_test_utils.h" | 17 #include "mojo/system/waiter_test_utils.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
19 | 19 |
20 namespace mojo { | 20 namespace mojo { |
21 namespace system { | 21 namespace system { |
22 namespace { | 22 namespace { |
23 | 23 |
24 TEST(WaiterListTest, BasicCancel) { | 24 TEST(WaiterListTest, BasicCancel) { |
25 MojoResult result; | 25 MojoResult result; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 MojoResult result; | 65 MojoResult result; |
66 uint32_t context; | 66 uint32_t context; |
67 | 67 |
68 // Awake immediately after thread start. | 68 // Awake immediately after thread start. |
69 { | 69 { |
70 WaiterList waiter_list; | 70 WaiterList waiter_list; |
71 test::SimpleWaiterThread thread(&result, &context); | 71 test::SimpleWaiterThread thread(&result, &context); |
72 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); | 72 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); |
73 thread.Start(); | 73 thread.Start(); |
74 waiter_list.AwakeWaitersForStateChange( | 74 waiter_list.AwakeWaitersForStateChange( |
75 WaitFlagsState(MOJO_HANDLE_SIGNAL_READABLE, | 75 HandleSignalsState(MOJO_HANDLE_SIGNAL_READABLE, |
76 MOJO_HANDLE_SIGNAL_READABLE | | 76 MOJO_HANDLE_SIGNAL_READABLE | |
77 MOJO_HANDLE_SIGNAL_WRITABLE)); | 77 MOJO_HANDLE_SIGNAL_WRITABLE)); |
78 waiter_list.RemoveWaiter(thread.waiter()); | 78 waiter_list.RemoveWaiter(thread.waiter()); |
79 } // Join |thread|. | 79 } // Join |thread|. |
80 EXPECT_EQ(MOJO_RESULT_OK, result); | 80 EXPECT_EQ(MOJO_RESULT_OK, result); |
81 EXPECT_EQ(1u, context); | 81 EXPECT_EQ(1u, context); |
82 | 82 |
83 // Awake before after thread start. | 83 // Awake before after thread start. |
84 { | 84 { |
85 WaiterList waiter_list; | 85 WaiterList waiter_list; |
86 test::SimpleWaiterThread thread(&result, &context); | 86 test::SimpleWaiterThread thread(&result, &context); |
87 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); | 87 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); |
88 waiter_list.AwakeWaitersForStateChange( | 88 waiter_list.AwakeWaitersForStateChange( |
89 WaitFlagsState(MOJO_HANDLE_SIGNAL_WRITABLE, | 89 HandleSignalsState(MOJO_HANDLE_SIGNAL_WRITABLE, |
90 MOJO_HANDLE_SIGNAL_READABLE | | 90 MOJO_HANDLE_SIGNAL_READABLE | |
91 MOJO_HANDLE_SIGNAL_WRITABLE)); | 91 MOJO_HANDLE_SIGNAL_WRITABLE)); |
92 waiter_list.RemoveWaiter(thread.waiter()); | 92 waiter_list.RemoveWaiter(thread.waiter()); |
93 waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay. | 93 waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay. |
94 thread.Start(); | 94 thread.Start(); |
95 } // Join |thread|. | 95 } // Join |thread|. |
96 EXPECT_EQ(MOJO_RESULT_OK, result); | 96 EXPECT_EQ(MOJO_RESULT_OK, result); |
97 EXPECT_EQ(2u, context); | 97 EXPECT_EQ(2u, context); |
98 | 98 |
99 // Awake some time after thread start. | 99 // Awake some time after thread start. |
100 { | 100 { |
101 WaiterList waiter_list; | 101 WaiterList waiter_list; |
102 test::SimpleWaiterThread thread(&result, &context); | 102 test::SimpleWaiterThread thread(&result, &context); |
103 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); | 103 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); |
104 thread.Start(); | 104 thread.Start(); |
105 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | 105 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); |
106 waiter_list.AwakeWaitersForStateChange( | 106 waiter_list.AwakeWaitersForStateChange( |
107 WaitFlagsState(MOJO_HANDLE_SIGNAL_READABLE, | 107 HandleSignalsState(MOJO_HANDLE_SIGNAL_READABLE, |
108 MOJO_HANDLE_SIGNAL_READABLE | | 108 MOJO_HANDLE_SIGNAL_READABLE | |
109 MOJO_HANDLE_SIGNAL_WRITABLE)); | 109 MOJO_HANDLE_SIGNAL_WRITABLE)); |
110 waiter_list.RemoveWaiter(thread.waiter()); | 110 waiter_list.RemoveWaiter(thread.waiter()); |
111 } // Join |thread|. | 111 } // Join |thread|. |
112 EXPECT_EQ(MOJO_RESULT_OK, result); | 112 EXPECT_EQ(MOJO_RESULT_OK, result); |
113 EXPECT_EQ(3u, context); | 113 EXPECT_EQ(3u, context); |
114 } | 114 } |
115 | 115 |
116 TEST(WaiterListTest, BasicAwakeUnsatisfiable) { | 116 TEST(WaiterListTest, BasicAwakeUnsatisfiable) { |
117 MojoResult result; | 117 MojoResult result; |
118 uint32_t context; | 118 uint32_t context; |
119 | 119 |
120 // Awake (for unsatisfiability) immediately after thread start. | 120 // Awake (for unsatisfiability) immediately after thread start. |
121 { | 121 { |
122 WaiterList waiter_list; | 122 WaiterList waiter_list; |
123 test::SimpleWaiterThread thread(&result, &context); | 123 test::SimpleWaiterThread thread(&result, &context); |
124 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); | 124 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); |
125 thread.Start(); | 125 thread.Start(); |
126 waiter_list.AwakeWaitersForStateChange( | 126 waiter_list.AwakeWaitersForStateChange( |
127 WaitFlagsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); | 127 HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, |
| 128 MOJO_HANDLE_SIGNAL_WRITABLE)); |
128 waiter_list.RemoveWaiter(thread.waiter()); | 129 waiter_list.RemoveWaiter(thread.waiter()); |
129 } // Join |thread|. | 130 } // Join |thread|. |
130 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | 131 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
131 EXPECT_EQ(1u, context); | 132 EXPECT_EQ(1u, context); |
132 | 133 |
133 // Awake (for unsatisfiability) before after thread start. | 134 // Awake (for unsatisfiability) before after thread start. |
134 { | 135 { |
135 WaiterList waiter_list; | 136 WaiterList waiter_list; |
136 test::SimpleWaiterThread thread(&result, &context); | 137 test::SimpleWaiterThread thread(&result, &context); |
137 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); | 138 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); |
138 waiter_list.AwakeWaitersForStateChange( | 139 waiter_list.AwakeWaitersForStateChange( |
139 WaitFlagsState(MOJO_HANDLE_SIGNAL_READABLE, | 140 HandleSignalsState(MOJO_HANDLE_SIGNAL_READABLE, |
140 MOJO_HANDLE_SIGNAL_READABLE)); | 141 MOJO_HANDLE_SIGNAL_READABLE)); |
141 waiter_list.RemoveWaiter(thread.waiter()); | 142 waiter_list.RemoveWaiter(thread.waiter()); |
142 thread.Start(); | 143 thread.Start(); |
143 } // Join |thread|. | 144 } // Join |thread|. |
144 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | 145 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
145 EXPECT_EQ(2u, context); | 146 EXPECT_EQ(2u, context); |
146 | 147 |
147 // Awake (for unsatisfiability) some time after thread start. | 148 // Awake (for unsatisfiability) some time after thread start. |
148 { | 149 { |
149 WaiterList waiter_list; | 150 WaiterList waiter_list; |
150 test::SimpleWaiterThread thread(&result, &context); | 151 test::SimpleWaiterThread thread(&result, &context); |
151 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); | 152 waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); |
152 thread.Start(); | 153 thread.Start(); |
153 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | 154 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); |
154 waiter_list.AwakeWaitersForStateChange( | 155 waiter_list.AwakeWaitersForStateChange( |
155 WaitFlagsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); | 156 HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, |
| 157 MOJO_HANDLE_SIGNAL_WRITABLE)); |
156 waiter_list.RemoveWaiter(thread.waiter()); | 158 waiter_list.RemoveWaiter(thread.waiter()); |
157 waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay. | 159 waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay. |
158 } // Join |thread|. | 160 } // Join |thread|. |
159 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | 161 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
160 EXPECT_EQ(3u, context); | 162 EXPECT_EQ(3u, context); |
161 } | 163 } |
162 | 164 |
163 TEST(WaiterListTest, MultipleWaiters) { | 165 TEST(WaiterListTest, MultipleWaiters) { |
164 MojoResult result1; | 166 MojoResult result1; |
165 MojoResult result2; | 167 MojoResult result2; |
(...skipping 25 matching lines...) Expand all Loading... |
191 { | 193 { |
192 WaiterList waiter_list; | 194 WaiterList waiter_list; |
193 test::SimpleWaiterThread thread1(&result1, &context1); | 195 test::SimpleWaiterThread thread1(&result1, &context1); |
194 waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); | 196 waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); |
195 thread1.Start(); | 197 thread1.Start(); |
196 test::SimpleWaiterThread thread2(&result2, &context2); | 198 test::SimpleWaiterThread thread2(&result2, &context2); |
197 waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4); | 199 waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4); |
198 thread2.Start(); | 200 thread2.Start(); |
199 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | 201 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); |
200 waiter_list.AwakeWaitersForStateChange( | 202 waiter_list.AwakeWaitersForStateChange( |
201 WaitFlagsState(MOJO_HANDLE_SIGNAL_READABLE, | 203 HandleSignalsState(MOJO_HANDLE_SIGNAL_READABLE, |
202 MOJO_HANDLE_SIGNAL_READABLE | | 204 MOJO_HANDLE_SIGNAL_READABLE | |
203 MOJO_HANDLE_SIGNAL_WRITABLE)); | 205 MOJO_HANDLE_SIGNAL_WRITABLE)); |
204 waiter_list.RemoveWaiter(thread1.waiter()); | 206 waiter_list.RemoveWaiter(thread1.waiter()); |
205 waiter_list.CancelAllWaiters(); | 207 waiter_list.CancelAllWaiters(); |
206 } // Join threads. | 208 } // Join threads. |
207 EXPECT_EQ(MOJO_RESULT_OK, result1); | 209 EXPECT_EQ(MOJO_RESULT_OK, result1); |
208 EXPECT_EQ(3u, context1); | 210 EXPECT_EQ(3u, context1); |
209 EXPECT_EQ(MOJO_RESULT_CANCELLED, result2); | 211 EXPECT_EQ(MOJO_RESULT_CANCELLED, result2); |
210 EXPECT_EQ(4u, context2); | 212 EXPECT_EQ(4u, context2); |
211 | 213 |
212 // Cancel one waiter, awake other for unsatisfiability. | 214 // Cancel one waiter, awake other for unsatisfiability. |
213 { | 215 { |
214 WaiterList waiter_list; | 216 WaiterList waiter_list; |
215 test::SimpleWaiterThread thread1(&result1, &context1); | 217 test::SimpleWaiterThread thread1(&result1, &context1); |
216 waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5); | 218 waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5); |
217 thread1.Start(); | 219 thread1.Start(); |
218 test::SimpleWaiterThread thread2(&result2, &context2); | 220 test::SimpleWaiterThread thread2(&result2, &context2); |
219 waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6); | 221 waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6); |
220 thread2.Start(); | 222 thread2.Start(); |
221 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | 223 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); |
222 waiter_list.AwakeWaitersForStateChange( | 224 waiter_list.AwakeWaitersForStateChange( |
223 WaitFlagsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); | 225 HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, |
| 226 MOJO_HANDLE_SIGNAL_READABLE)); |
224 waiter_list.RemoveWaiter(thread2.waiter()); | 227 waiter_list.RemoveWaiter(thread2.waiter()); |
225 waiter_list.CancelAllWaiters(); | 228 waiter_list.CancelAllWaiters(); |
226 } // Join threads. | 229 } // Join threads. |
227 EXPECT_EQ(MOJO_RESULT_CANCELLED, result1); | 230 EXPECT_EQ(MOJO_RESULT_CANCELLED, result1); |
228 EXPECT_EQ(5u, context1); | 231 EXPECT_EQ(5u, context1); |
229 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); | 232 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); |
230 EXPECT_EQ(6u, context2); | 233 EXPECT_EQ(6u, context2); |
231 | 234 |
232 // Cancel one waiter, awake other for unsatisfiability. | 235 // Cancel one waiter, awake other for unsatisfiability. |
233 { | 236 { |
234 WaiterList waiter_list; | 237 WaiterList waiter_list; |
235 test::SimpleWaiterThread thread1(&result1, &context1); | 238 test::SimpleWaiterThread thread1(&result1, &context1); |
236 waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7); | 239 waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7); |
237 thread1.Start(); | 240 thread1.Start(); |
238 | 241 |
239 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | 242 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); |
240 | 243 |
241 // Should do nothing. | 244 // Should do nothing. |
242 waiter_list.AwakeWaitersForStateChange( | 245 waiter_list.AwakeWaitersForStateChange( |
243 WaitFlagsState(MOJO_HANDLE_SIGNAL_NONE, | 246 HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, |
244 MOJO_HANDLE_SIGNAL_READABLE | | 247 MOJO_HANDLE_SIGNAL_READABLE | |
245 MOJO_HANDLE_SIGNAL_WRITABLE)); | 248 MOJO_HANDLE_SIGNAL_WRITABLE)); |
246 | 249 |
247 test::SimpleWaiterThread thread2(&result2, &context2); | 250 test::SimpleWaiterThread thread2(&result2, &context2); |
248 waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8); | 251 waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8); |
249 thread2.Start(); | 252 thread2.Start(); |
250 | 253 |
251 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | 254 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); |
252 | 255 |
253 // Awake #1. | 256 // Awake #1. |
254 waiter_list.AwakeWaitersForStateChange( | 257 waiter_list.AwakeWaitersForStateChange( |
255 WaitFlagsState(MOJO_HANDLE_SIGNAL_READABLE, | 258 HandleSignalsState(MOJO_HANDLE_SIGNAL_READABLE, |
256 MOJO_HANDLE_SIGNAL_READABLE | | 259 MOJO_HANDLE_SIGNAL_READABLE | |
257 MOJO_HANDLE_SIGNAL_WRITABLE)); | 260 MOJO_HANDLE_SIGNAL_WRITABLE)); |
258 waiter_list.RemoveWaiter(thread1.waiter()); | 261 waiter_list.RemoveWaiter(thread1.waiter()); |
259 | 262 |
260 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | 263 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); |
261 | 264 |
262 test::SimpleWaiterThread thread3(&result3, &context3); | 265 test::SimpleWaiterThread thread3(&result3, &context3); |
263 waiter_list.AddWaiter(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9); | 266 waiter_list.AddWaiter(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9); |
264 thread3.Start(); | 267 thread3.Start(); |
265 | 268 |
266 test::SimpleWaiterThread thread4(&result4, &context4); | 269 test::SimpleWaiterThread thread4(&result4, &context4); |
267 waiter_list.AddWaiter(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10); | 270 waiter_list.AddWaiter(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10); |
268 thread4.Start(); | 271 thread4.Start(); |
269 | 272 |
270 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | 273 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); |
271 | 274 |
272 // Awake #2 and #3 for unsatisfiability. | 275 // Awake #2 and #3 for unsatisfiability. |
273 waiter_list.AwakeWaitersForStateChange( | 276 waiter_list.AwakeWaitersForStateChange( |
274 WaitFlagsState(MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); | 277 HandleSignalsState(MOJO_HANDLE_SIGNAL_NONE, |
| 278 MOJO_HANDLE_SIGNAL_READABLE)); |
275 waiter_list.RemoveWaiter(thread2.waiter()); | 279 waiter_list.RemoveWaiter(thread2.waiter()); |
276 waiter_list.RemoveWaiter(thread3.waiter()); | 280 waiter_list.RemoveWaiter(thread3.waiter()); |
277 | 281 |
278 // Cancel #4. | 282 // Cancel #4. |
279 waiter_list.CancelAllWaiters(); | 283 waiter_list.CancelAllWaiters(); |
280 } // Join threads. | 284 } // Join threads. |
281 EXPECT_EQ(MOJO_RESULT_OK, result1); | 285 EXPECT_EQ(MOJO_RESULT_OK, result1); |
282 EXPECT_EQ(7u, context1); | 286 EXPECT_EQ(7u, context1); |
283 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); | 287 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); |
284 EXPECT_EQ(8u, context2); | 288 EXPECT_EQ(8u, context2); |
285 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result3); | 289 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result3); |
286 EXPECT_EQ(9u, context3); | 290 EXPECT_EQ(9u, context3); |
287 EXPECT_EQ(MOJO_RESULT_CANCELLED, result4); | 291 EXPECT_EQ(MOJO_RESULT_CANCELLED, result4); |
288 EXPECT_EQ(10u, context4); | 292 EXPECT_EQ(10u, context4); |
289 } | 293 } |
290 | 294 |
291 } // namespace | 295 } // namespace |
292 } // namespace system | 296 } // namespace system |
293 } // namespace mojo | 297 } // namespace mojo |
OLD | NEW |