OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/message_loop/message_pump_glib.h" | 5 #include "base/message_loop/message_pump_glib.h" |
6 | 6 |
7 #include <glib.h> | 7 #include <glib.h> |
8 #include <math.h> | 8 #include <math.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 | 52 |
53 bool HandleCheck() { | 53 bool HandleCheck() { |
54 if (events_.empty()) | 54 if (events_.empty()) |
55 return false; | 55 return false; |
56 return events_[0].time <= Time::NowFromSystemTime(); | 56 return events_[0].time <= Time::NowFromSystemTime(); |
57 } | 57 } |
58 | 58 |
59 void HandleDispatch() { | 59 void HandleDispatch() { |
60 if (events_.empty()) | 60 if (events_.empty()) |
61 return; | 61 return; |
62 Event event = events_[0]; | 62 Event event = std::move(events_[0]); |
63 events_.erase(events_.begin()); | 63 events_.erase(events_.begin()); |
64 ++processed_events_; | 64 ++processed_events_; |
65 if (!event.callback.is_null()) | 65 if (!event.callback.is_null()) |
66 event.callback.Run(); | 66 std::move(event.callback).Run(); |
67 else if (!event.task.is_null()) | 67 else if (!event.task.is_null()) |
68 event.task.Run(); | 68 std::move(event.task).Run(); |
69 } | 69 } |
70 | 70 |
71 // Adds an event to the queue. When "handled", executes |callback|. | 71 // Adds an event to the queue. When "handled", executes |callback|. |
72 // delay_ms is relative to the last event if any, or to Now() otherwise. | 72 // delay_ms is relative to the last event if any, or to Now() otherwise. |
73 void AddEvent(int delay_ms, const Closure& callback) { | 73 void AddEvent(int delay_ms, OnceClosure callback) { |
74 AddEventHelper(delay_ms, callback, Closure()); | 74 AddEventHelper(delay_ms, std::move(callback), OnceClosure()); |
75 } | 75 } |
76 | 76 |
77 void AddDummyEvent(int delay_ms) { | 77 void AddDummyEvent(int delay_ms) { |
78 AddEventHelper(delay_ms, Closure(), Closure()); | 78 AddEventHelper(delay_ms, OnceClosure(), OnceClosure()); |
79 } | 79 } |
80 | 80 |
81 void AddEventAsTask(int delay_ms, const Closure& task) { | 81 void AddEventAsTask(int delay_ms, OnceClosure task) { |
82 AddEventHelper(delay_ms, Closure(), task); | 82 AddEventHelper(delay_ms, OnceClosure(), std::move(task)); |
83 } | 83 } |
84 | 84 |
85 void Reset() { | 85 void Reset() { |
86 processed_events_ = 0; | 86 processed_events_ = 0; |
87 events_.clear(); | 87 events_.clear(); |
88 } | 88 } |
89 | 89 |
90 int processed_events() const { return processed_events_; } | 90 int processed_events() const { return processed_events_; } |
91 | 91 |
92 private: | 92 private: |
93 struct Event { | 93 struct Event { |
94 Time time; | 94 Time time; |
95 Closure callback; | 95 OnceClosure callback; |
96 Closure task; | 96 OnceClosure task; |
97 }; | 97 }; |
98 | 98 |
99 struct Source : public GSource { | 99 struct Source : public GSource { |
100 EventInjector* injector; | 100 EventInjector* injector; |
101 }; | 101 }; |
102 | 102 |
103 void AddEventHelper( | 103 void AddEventHelper(int delay_ms, OnceClosure callback, OnceClosure task) { |
104 int delay_ms, const Closure& callback, const Closure& task) { | |
105 Time last_time; | 104 Time last_time; |
106 if (!events_.empty()) | 105 if (!events_.empty()) |
107 last_time = (events_.end()-1)->time; | 106 last_time = (events_.end()-1)->time; |
108 else | 107 else |
109 last_time = Time::NowFromSystemTime(); | 108 last_time = Time::NowFromSystemTime(); |
110 | 109 |
111 Time future = last_time + TimeDelta::FromMilliseconds(delay_ms); | 110 Time future = last_time + TimeDelta::FromMilliseconds(delay_ms); |
112 EventInjector::Event event = {future, callback, task}; | 111 EventInjector::Event event = {future, std::move(callback), std::move(task)}; |
113 events_.push_back(event); | 112 events_.push_back(std::move(event)); |
114 } | 113 } |
115 | 114 |
116 static gboolean Prepare(GSource* source, gint* timeout_ms) { | 115 static gboolean Prepare(GSource* source, gint* timeout_ms) { |
117 *timeout_ms = static_cast<Source*>(source)->injector->HandlePrepare(); | 116 *timeout_ms = static_cast<Source*>(source)->injector->HandlePrepare(); |
118 return FALSE; | 117 return FALSE; |
119 } | 118 } |
120 | 119 |
121 static gboolean Check(GSource* source) { | 120 static gboolean Check(GSource* source) { |
122 return static_cast<Source*>(source)->injector->HandleCheck(); | 121 return static_cast<Source*>(source)->injector->HandleCheck(); |
123 } | 122 } |
(...skipping 23 matching lines...) Expand all Loading... |
147 ++*value; | 146 ++*value; |
148 } | 147 } |
149 | 148 |
150 // Checks how many events have been processed by the injector. | 149 // Checks how many events have been processed by the injector. |
151 void ExpectProcessedEvents(EventInjector* injector, int count) { | 150 void ExpectProcessedEvents(EventInjector* injector, int count) { |
152 EXPECT_EQ(injector->processed_events(), count); | 151 EXPECT_EQ(injector->processed_events(), count); |
153 } | 152 } |
154 | 153 |
155 // Posts a task on the current message loop. | 154 // Posts a task on the current message loop. |
156 void PostMessageLoopTask(const tracked_objects::Location& from_here, | 155 void PostMessageLoopTask(const tracked_objects::Location& from_here, |
157 const Closure& task) { | 156 OnceClosure task) { |
158 ThreadTaskRunnerHandle::Get()->PostTask(from_here, task); | 157 ThreadTaskRunnerHandle::Get()->PostTask(from_here, std::move(task)); |
159 } | 158 } |
160 | 159 |
161 // Test fixture. | 160 // Test fixture. |
162 class MessagePumpGLibTest : public testing::Test { | 161 class MessagePumpGLibTest : public testing::Test { |
163 public: | 162 public: |
164 MessagePumpGLibTest() : loop_(NULL), injector_(NULL) { } | 163 MessagePumpGLibTest() : loop_(NULL), injector_(NULL) { } |
165 | 164 |
166 // Overridden from testing::Test: | 165 // Overridden from testing::Test: |
167 void SetUp() override { | 166 void SetUp() override { |
168 loop_ = new MessageLoop(MessageLoop::TYPE_UI); | 167 loop_ = new MessageLoop(MessageLoop::TYPE_UI); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 } | 200 } |
202 | 201 |
203 TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) { | 202 TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) { |
204 // Checks that tasks posted by events are executed before the next event if | 203 // Checks that tasks posted by events are executed before the next event if |
205 // the posted task queue is empty. | 204 // the posted task queue is empty. |
206 // MessageLoop doesn't make strong guarantees that it is the case, but the | 205 // MessageLoop doesn't make strong guarantees that it is the case, but the |
207 // current implementation ensures it and the tests below rely on it. | 206 // current implementation ensures it and the tests below rely on it. |
208 // If changes cause this test to fail, it is reasonable to change it, but | 207 // If changes cause this test to fail, it is reasonable to change it, but |
209 // TestWorkWhileWaitingForEvents and TestEventsWhileWaitingForWork have to be | 208 // TestWorkWhileWaitingForEvents and TestEventsWhileWaitingForWork have to be |
210 // changed accordingly, otherwise they can become flaky. | 209 // changed accordingly, otherwise they can become flaky. |
211 injector()->AddEventAsTask(0, Bind(&DoNothing)); | 210 injector()->AddEventAsTask(0, BindOnce(&DoNothing)); |
212 Closure check_task = | 211 OnceClosure check_task = |
213 Bind(&ExpectProcessedEvents, Unretained(injector()), 2); | 212 BindOnce(&ExpectProcessedEvents, Unretained(injector()), 2); |
214 Closure posted_task = | 213 OnceClosure posted_task = |
215 Bind(&PostMessageLoopTask, FROM_HERE, check_task); | 214 BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task)); |
216 injector()->AddEventAsTask(0, posted_task); | 215 injector()->AddEventAsTask(0, std::move(posted_task)); |
217 injector()->AddEventAsTask(0, Bind(&DoNothing)); | 216 injector()->AddEventAsTask(0, BindOnce(&DoNothing)); |
218 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); | 217 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); |
219 RunLoop().Run(); | 218 RunLoop().Run(); |
220 EXPECT_EQ(4, injector()->processed_events()); | 219 EXPECT_EQ(4, injector()->processed_events()); |
221 | 220 |
222 injector()->Reset(); | 221 injector()->Reset(); |
223 injector()->AddEventAsTask(0, Bind(&DoNothing)); | 222 injector()->AddEventAsTask(0, BindOnce(&DoNothing)); |
224 check_task = | 223 check_task = BindOnce(&ExpectProcessedEvents, Unretained(injector()), 2); |
225 Bind(&ExpectProcessedEvents, Unretained(injector()), 2); | 224 posted_task = |
226 posted_task = Bind(&PostMessageLoopTask, FROM_HERE, check_task); | 225 BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task)); |
227 injector()->AddEventAsTask(0, posted_task); | 226 injector()->AddEventAsTask(0, std::move(posted_task)); |
228 injector()->AddEventAsTask(10, Bind(&DoNothing)); | 227 injector()->AddEventAsTask(10, BindOnce(&DoNothing)); |
229 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); | 228 injector()->AddEvent(0, MessageLoop::QuitWhenIdleClosure()); |
230 RunLoop().Run(); | 229 RunLoop().Run(); |
231 EXPECT_EQ(4, injector()->processed_events()); | 230 EXPECT_EQ(4, injector()->processed_events()); |
232 } | 231 } |
233 | 232 |
234 TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) { | 233 TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) { |
235 int task_count = 0; | 234 int task_count = 0; |
236 // Tests that we process tasks while waiting for new events. | 235 // Tests that we process tasks while waiting for new events. |
237 // The event queue is empty at first. | 236 // The event queue is empty at first. |
238 for (int i = 0; i < 10; ++i) { | 237 for (int i = 0; i < 10; ++i) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 271 |
273 TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) { | 272 TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) { |
274 // Tests that we process events while waiting for work. | 273 // Tests that we process events while waiting for work. |
275 // The event queue is empty at first. | 274 // The event queue is empty at first. |
276 for (int i = 0; i < 10; ++i) { | 275 for (int i = 0; i < 10; ++i) { |
277 injector()->AddDummyEvent(0); | 276 injector()->AddDummyEvent(0); |
278 } | 277 } |
279 // After all the events have been processed, post a task that will check that | 278 // After all the events have been processed, post a task that will check that |
280 // the events have been processed (note: the task executes after the event | 279 // the events have been processed (note: the task executes after the event |
281 // that posted it has been handled, so we expect 11 at that point). | 280 // that posted it has been handled, so we expect 11 at that point). |
282 Closure check_task = | 281 OnceClosure check_task = |
283 Bind(&ExpectProcessedEvents, Unretained(injector()), 11); | 282 BindOnce(&ExpectProcessedEvents, Unretained(injector()), 11); |
284 Closure posted_task = | 283 OnceClosure posted_task = |
285 Bind(&PostMessageLoopTask, FROM_HERE, check_task); | 284 BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task)); |
286 injector()->AddEventAsTask(10, posted_task); | 285 injector()->AddEventAsTask(10, std::move(posted_task)); |
287 | 286 |
288 // And then quit (relies on the condition tested by TestEventTaskInterleave). | 287 // And then quit (relies on the condition tested by TestEventTaskInterleave). |
289 injector()->AddEvent(10, MessageLoop::QuitWhenIdleClosure()); | 288 injector()->AddEvent(10, MessageLoop::QuitWhenIdleClosure()); |
290 RunLoop().Run(); | 289 RunLoop().Run(); |
291 | 290 |
292 EXPECT_EQ(12, injector()->processed_events()); | 291 EXPECT_EQ(12, injector()->processed_events()); |
293 } | 292 } |
294 | 293 |
295 namespace { | 294 namespace { |
296 | 295 |
(...skipping 20 matching lines...) Expand all Loading... |
317 } | 316 } |
318 } | 317 } |
319 | 318 |
320 void FromEvent() { | 319 void FromEvent() { |
321 if (event_count_ > 0) { | 320 if (event_count_ > 0) { |
322 --event_count_; | 321 --event_count_; |
323 } | 322 } |
324 if (task_count_ == 0 && event_count_ == 0) { | 323 if (task_count_ == 0 && event_count_ == 0) { |
325 MessageLoop::current()->QuitWhenIdle(); | 324 MessageLoop::current()->QuitWhenIdle(); |
326 } else { | 325 } else { |
327 injector_->AddEventAsTask( | 326 injector_->AddEventAsTask(0, |
328 0, Bind(&ConcurrentHelper::FromEvent, this)); | 327 BindOnce(&ConcurrentHelper::FromEvent, this)); |
329 } | 328 } |
330 } | 329 } |
331 | 330 |
332 int event_count() const { return event_count_; } | 331 int event_count() const { return event_count_; } |
333 int task_count() const { return task_count_; } | 332 int task_count() const { return task_count_; } |
334 | 333 |
335 private: | 334 private: |
336 friend class RefCounted<ConcurrentHelper>; | 335 friend class RefCounted<ConcurrentHelper>; |
337 | 336 |
338 ~ConcurrentHelper() {} | 337 ~ConcurrentHelper() {} |
(...skipping 11 matching lines...) Expand all Loading... |
350 TEST_F(MessagePumpGLibTest, TestConcurrentEventPostedTask) { | 349 TEST_F(MessagePumpGLibTest, TestConcurrentEventPostedTask) { |
351 // Tests that posted tasks don't starve events, nor the opposite. | 350 // Tests that posted tasks don't starve events, nor the opposite. |
352 // We use the helper class above. We keep both event and posted task queues | 351 // We use the helper class above. We keep both event and posted task queues |
353 // full, the helper verifies that both tasks and events get processed. | 352 // full, the helper verifies that both tasks and events get processed. |
354 // If that is not the case, either event_count_ or task_count_ will not get | 353 // If that is not the case, either event_count_ or task_count_ will not get |
355 // to 0, and MessageLoop::QuitWhenIdle() will never be called. | 354 // to 0, and MessageLoop::QuitWhenIdle() will never be called. |
356 scoped_refptr<ConcurrentHelper> helper = new ConcurrentHelper(injector()); | 355 scoped_refptr<ConcurrentHelper> helper = new ConcurrentHelper(injector()); |
357 | 356 |
358 // Add 2 events to the queue to make sure it is always full (when we remove | 357 // Add 2 events to the queue to make sure it is always full (when we remove |
359 // the event before processing it). | 358 // the event before processing it). |
360 injector()->AddEventAsTask( | 359 injector()->AddEventAsTask(0, BindOnce(&ConcurrentHelper::FromEvent, helper)); |
361 0, Bind(&ConcurrentHelper::FromEvent, helper)); | 360 injector()->AddEventAsTask(0, BindOnce(&ConcurrentHelper::FromEvent, helper)); |
362 injector()->AddEventAsTask( | |
363 0, Bind(&ConcurrentHelper::FromEvent, helper)); | |
364 | 361 |
365 // Similarly post 2 tasks. | 362 // Similarly post 2 tasks. |
366 loop()->task_runner()->PostTask( | 363 loop()->task_runner()->PostTask( |
367 FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, helper)); | 364 FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, helper)); |
368 loop()->task_runner()->PostTask( | 365 loop()->task_runner()->PostTask( |
369 FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, helper)); | 366 FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, helper)); |
370 | 367 |
371 RunLoop().Run(); | 368 RunLoop().Run(); |
372 EXPECT_EQ(0, helper->event_count()); | 369 EXPECT_EQ(0, helper->event_count()); |
373 EXPECT_EQ(0, helper->task_count()); | 370 EXPECT_EQ(0, helper->task_count()); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 // Tests that events and posted tasks are correctly executed if the message | 517 // Tests that events and posted tasks are correctly executed if the message |
521 // loop is not run by MessageLoop::Run() but by a straight Gtk loop. | 518 // loop is not run by MessageLoop::Run() but by a straight Gtk loop. |
522 // Note that in this case we don't make strong guarantees about niceness | 519 // Note that in this case we don't make strong guarantees about niceness |
523 // between events and posted tasks. | 520 // between events and posted tasks. |
524 loop()->task_runner()->PostTask( | 521 loop()->task_runner()->PostTask( |
525 FROM_HERE, BindOnce(&TestGtkLoopInternal, Unretained(injector()))); | 522 FROM_HERE, BindOnce(&TestGtkLoopInternal, Unretained(injector()))); |
526 RunLoop().Run(); | 523 RunLoop().Run(); |
527 } | 524 } |
528 | 525 |
529 } // namespace base | 526 } // namespace base |
OLD | NEW |