Chromium Code Reviews| 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 #ifndef BASE_TASK_H_ | 5 #ifndef BASE_TASK_H_ |
| 6 #define BASE_TASK_H_ | 6 #define BASE_TASK_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include "base/base_api.h" | 9 #include "base/base_api.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/debug/alias.h" | 11 #include "base/debug/alias.h" |
| 12 #include "base/memory/raw_scoped_refptr_mismatch_checker.h" | 12 #include "base/memory/raw_scoped_refptr_mismatch_checker.h" |
| 13 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
| 14 #include "base/tracked.h" | 14 #include "base/tracked.h" |
| 15 #include "base/tuple.h" | 15 #include "base/tuple.h" |
| 16 | 16 |
| 17 class MessageLoop; | |
| 18 | |
| 17 namespace base { | 19 namespace base { |
| 18 const size_t kDeadTask = 0xDEAD7A53; | 20 const size_t kDeadTask = 0xDEAD7A53; |
| 21 class MessageLoopProxy; | |
| 19 } | 22 } |
| 20 | 23 |
| 21 // Task ------------------------------------------------------------------------ | 24 // Task ------------------------------------------------------------------------ |
| 22 // | 25 // |
| 23 // A task is a generic runnable thingy, usually used for running code on a | 26 // A task is a generic runnable thingy, usually used for running code on a |
| 24 // different thread or for scheduling future tasks off of the message loop. | 27 // different thread or for scheduling future tasks off of the message loop. |
| 25 | 28 |
| 26 class BASE_API Task : public tracked_objects::Tracked { | 29 class BASE_API Task : public tracked_objects::Tracked { |
| 27 public: | 30 public: |
| 28 Task(); | 31 Task(); |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 560 Task* Release(); | 563 Task* Release(); |
| 561 | 564 |
| 562 private: | 565 private: |
| 563 Task* task_; | 566 Task* task_; |
| 564 | 567 |
| 565 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTaskRunner); | 568 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTaskRunner); |
| 566 }; | 569 }; |
| 567 | 570 |
| 568 namespace internal { | 571 namespace internal { |
| 569 | 572 |
| 570 class PostTaskAndReplyRelay { | 573 // This relay class remembers the MessageLoop that it was created on, and |
| 574 // ensures that both the |task| and |reply| Closures are deleted on this same | |
| 575 // thread. | |
| 576 // | |
| 577 // If this is not possible because the originating MessageLoop is no longer | |
| 578 // available, the the |task| and |reply| Closures are leaked. Leaking is | |
| 579 // considered preferable to having a thread-safetey violations caused by | |
| 580 // invoking the Closure destructor on the wrong thread. | |
| 581 class PostTaskAndReplyRelay : | |
| 582 public RefCountedThreadSafe<PostTaskAndReplyRelay, ManualDestruction> { | |
| 571 public: | 583 public: |
| 572 PostTaskAndReplyRelay(const Closure& task, const Closure& reply); | 584 PostTaskAndReplyRelay(const tracked_objects::Location& from_here, |
| 585 const Closure& task, const Closure& reply); | |
| 573 | 586 |
| 574 ~PostTaskAndReplyRelay(); | 587 ~PostTaskAndReplyRelay(); |
| 575 | 588 |
| 576 void Run(); | 589 void Run(); |
| 577 | 590 |
| 578 private: | 591 private: |
| 592 // An alternate implementation would just call "delete this;" inside | |
| 593 // RunReplyAndSelfDestruct() instead of using refcounts with | |
| 594 // ManualDestruction. While this works mostly, it misses the case where the | |
| 595 // target MessageLoop is in shutdown, but the origin MessageLoop is not. | |
|
willchan no longer on Chromium
2011/07/06 22:10:26
I think this is unnecessarily complicated and this
awong
2011/08/15 22:07:55
Okay, went back to simple delete.
| |
| 596 // | |
| 597 // Using a refcount allows us to still properly delete the relay object even | |
| 598 // if PostTaskAndReplyRelay::Run() is never executed. | |
| 599 friend class base::ManualDestruction; | |
| 600 static void DoManualDestruction(const PostTaskAndReplyRelay* obj); | |
| 601 | |
| 579 void RunReplyAndSelfDestruct(); | 602 void RunReplyAndSelfDestruct(); |
| 580 | 603 |
| 581 base::Closure task_; | 604 tracked_objects::Location from_here_; |
| 582 base::Closure reply_; | 605 scoped_refptr<MessageLoopProxy> origin_loop_; |
| 606 Closure task_; | |
| 607 Closure reply_; | |
| 583 }; | 608 }; |
| 609 | |
| 584 } // namespace internal | 610 } // namespace internal |
| 585 | 611 |
| 586 template <typename MessageLoopType, typename ResponseType> | 612 void PostTaskAndReply(MessageLoop* loop, |
| 587 void PostTaskAndReply(MessageLoopType loop, const Closure& task, | 613 const tracked_objects::Location& from_here, |
| 588 const Closure& reply) { | 614 const Closure& task, |
| 589 PostTaskAndReplyRelay* relay = new PostTaskAndReplyRelay(task, reply); | 615 const Closure& reply); |
| 590 loop.PostTask(&PostTaskAndReplyRelay::Run, base::Unretained(relay)); | |
| 591 } | |
| 592 | |
| 593 template <typename MessageLoopType, typename ResponseType> | |
| 594 void PostTaskAndReply<MessageLoopType, ResponseType>( | |
| 595 MessageLoopType* loop, const Closure& task, const Closure& reply) { | |
| 596 PostTaskAndReplyRelay* relay = new PostTaskAndReplyRelay(task, reply); | |
| 597 loop->PostTask(&PostTaskAndReplyRelay::Run, base::Unretained(relay)); | |
| 598 } | |
| 599 | |
| 600 } // namespace base | 616 } // namespace base |
| 601 | 617 |
| 602 #endif // BASE_TASK_H_ | 618 #endif // BASE_TASK_H_ |
| OLD | NEW |