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 |