task.h revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_TASK_H_
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_TASK_H_
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/non_thread_safe.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/raw_scoped_refptr_mismatch_checker.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/tracked.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/tuple.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/weak_ptr.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Task ------------------------------------------------------------------------
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A task is a generic runnable thingy, usually used for running code on a
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// different thread or for scheduling future tasks off of the message loop.
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass Task : public tracked_objects::Tracked {
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Task();
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~Task();
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Tasks are automatically deleted after Run is called.
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run() = 0;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass CancelableTask : public Task {
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CancelableTask();
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~CancelableTask();
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Not all tasks support cancellation.
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Cancel() = 0;
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Scoped Factories ------------------------------------------------------------
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// These scoped factory objects can be used by non-refcounted objects to safely
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// place tasks in a message loop.  Each factory guarantees that the tasks it
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// produces will not run after the factory is destroyed.  Commonly, factories
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// are declared as class members, so the class' tasks will automatically cancel
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// when the class instance is destroyed.
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Exampe Usage:
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// class MyClass {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  private:
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   // This factory will be used to schedule invocations of SomeMethod.
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   ScopedRunnableMethodFactory<MyClass> some_method_factory_;
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  public:
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   // It is safe to suppress warning 4355 here.
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   MyClass() : ALLOW_THIS_IN_INITIALIZER_LIST(some_method_factory_(this)) { }
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   void SomeMethod() {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     // If this function might be called directly, you might want to revoke
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     // any outstanding runnable methods scheduled to call it.  If it's not
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     // referenced other than by the factory, this is unnecessary.
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     some_method_factory_.RevokeAll();
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     ...
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   }
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   void ScheduleSomeMethod() {
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     // If you'd like to only only have one pending task at a time, test for
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     // |empty| before manufacturing another task.
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     if (!some_method_factory_.empty())
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//       return;
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     // The factories are not thread safe, so always invoke on
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//     // |MessageLoop::current()|.
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//     MessageLoop::current()->PostDelayedTask(
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//         FROM_HERE,
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//         some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod),
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//         kSomeMethodDelayMS);
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   }
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// };
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A ScopedRunnableMethodFactory creates runnable methods for a specified
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// object.  This is particularly useful for generating callbacks for
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// non-reference counted objects when the factory is a member of the object.
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<class T>
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ScopedRunnableMethodFactory {
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) {
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  template <class Method>
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inline CancelableTask* NewRunnableMethod(Method method) {
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new RunnableMethod<Method, Tuple0>(
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        weak_factory_.GetWeakPtr(), method, MakeTuple());
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  template <class Method, class A>
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inline CancelableTask* NewRunnableMethod(Method method, const A& a) {
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new RunnableMethod<Method, Tuple1<A> >(
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        weak_factory_.GetWeakPtr(), method, MakeTuple(a));
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  template <class Method, class A, class B>
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inline CancelableTask* NewRunnableMethod(Method method, const A& a,
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const B& b) {
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new RunnableMethod<Method, Tuple2<A, B> >(
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b));
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  template <class Method, class A, class B, class C>
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inline CancelableTask* NewRunnableMethod(Method method,
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const A& a,
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const B& b,
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const C& c) {
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new RunnableMethod<Method, Tuple3<A, B, C> >(
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c));
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  template <class Method, class A, class B, class C, class D>
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inline CancelableTask* NewRunnableMethod(Method method,
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const A& a,
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const B& b,
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const C& c,
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const D& d) {
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new RunnableMethod<Method, Tuple4<A, B, C, D> >(
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d));
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  template <class Method, class A, class B, class C, class D, class E>
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inline CancelableTask* NewRunnableMethod(Method method,
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const A& a,
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const B& b,
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const C& c,
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const D& d,
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 const E& e) {
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new RunnableMethod<Method, Tuple5<A, B, C, D, E> >(
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d, e));
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool empty() const { return !weak_factory_.HasWeakPtrs(); }
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  template <class Method, class Params>
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class RunnableMethod : public CancelableTask {
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RunnableMethod(const base::WeakPtr<T>& obj, Method meth,
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   const Params& params)
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        : obj_(obj),
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          meth_(meth),
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          params_(params) {
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     badscopedrunnablemethodparams);
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual void Run() {
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (obj_)
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DispatchToMethod(obj_.get(), meth_, params_);
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual void Cancel() {
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      obj_.reset();
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base::WeakPtr<T> obj_;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Method meth_;
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Params params_;
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DISALLOW_COPY_AND_ASSIGN(RunnableMethod);
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::WeakPtrFactory<T> weak_factory_;
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// General task implementations ------------------------------------------------
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Task to delete an object
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<class T>
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass DeleteTask : public CancelableTask {
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit DeleteTask(T* obj) : obj_(obj) {
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run() {
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete obj_;
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Cancel() {
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    obj_ = NULL;
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  T* obj_;
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Task to Release() an object
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<class T>
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ReleaseTask : public CancelableTask {
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit ReleaseTask(T* obj) : obj_(obj) {
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run() {
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (obj_)
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      obj_->Release();
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Cancel() {
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    obj_ = NULL;
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  T* obj_;
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// RunnableMethodTraits --------------------------------------------------------
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This traits-class is used by RunnableMethod to manage the lifetime of the
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// callee object.  By default, it is assumed that the callee supports AddRef
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and Release methods.  A particular class can specialize this template to
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// define other lifetime management.  For example, if the callee is known to
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// live longer than the RunnableMethod object, then a RunnableMethodTraits
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// struct could be defined with empty RetainCallee and ReleaseCallee methods.
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// for declaring a RunnableMethodTraits that disables refcounting.
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T>
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct RunnableMethodTraits {
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RunnableMethodTraits() {
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NDEBUG
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    origin_thread_id_ = PlatformThread::CurrentId();
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~RunnableMethodTraits() {
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NDEBUG
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If destroyed on a separate thread, then we had better have been using
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // thread-safe reference counting!
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (origin_thread_id_ != PlatformThread::CurrentId())
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK(T::ImplementsThreadSafeReferenceCounting());
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void RetainCallee(T* obj) {
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NDEBUG
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Catch NewRunnableMethod being called in an object's constructor.  This
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // isn't safe since the method can be invoked before the constructor
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // completes, causing the object to be deleted.
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    obj->AddRef();
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    obj->Release();
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    obj->AddRef();
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ReleaseCallee(T* obj) {
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    obj->Release();
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NDEBUG
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PlatformThreadId origin_thread_id_;
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Convenience macro for declaring a RunnableMethodTraits that disables
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// refcounting of a class.  This is useful if you know that the callee
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will outlive the RunnableMethod object and thus do not need the ref counts.
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// global namespace scope.  Example:
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   namespace foo {
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   class Bar {
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//     ...
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   };
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   }  // namespace foo
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar)
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// class.
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  template <>                                      \
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct RunnableMethodTraits<TypeName> {          \
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void RetainCallee(TypeName* manager) {}        \
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void ReleaseCallee(TypeName* manager) {}       \
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// RunnableMethod and RunnableFunction -----------------------------------------
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Runnable methods are a type of task that call a function on an object when
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// they are run. We implement both an object and a set of NewRunnableMethod and
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// NewRunnableFunction functions for convenience. These functions are
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// overloaded and will infer the template types, simplifying calling code.
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The template definitions all use the following names:
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// T                - the class type of the object you're supplying
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//                    this is not needed for the Static version of the call
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Method/Function  - the signature of a pointer to the method or function you
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//                    want to call
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Param            - the parameter(s) to the method, possibly packed as a Tuple
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A                - the first parameter (if any) to the method
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// B                - the second parameter (if any) to the mathod
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Put these all together and you get an object that can call a method whose
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// signature is:
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   R T::MyFunction([A[, B]])
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Usage:
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]])
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]])
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// RunnableMethod and NewRunnableMethod implementation -------------------------
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class Params>
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass RunnableMethod : public CancelableTask {
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RunnableMethod(T* obj, Method meth, const Params& params)
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : obj_(obj), meth_(meth), params_(params) {
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    traits_.RetainCallee(obj_);
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value),
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   badrunnablemethodparams);
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~RunnableMethod() {
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReleaseCallee();
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run() {
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (obj_)
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DispatchToMethod(obj_, meth_, params_);
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Cancel() {
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReleaseCallee();
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ReleaseCallee() {
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (obj_) {
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      traits_.ReleaseCallee(obj_);
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      obj_ = NULL;
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  T* obj_;
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Method meth_;
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Params params_;
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RunnableMethodTraits<T> traits_;
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method>
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method) {
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class A>
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T, Method, Tuple1<A> >(object,
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                   method,
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                   MakeTuple(a));
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class A, class B>
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method,
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst A& a, const B& b) {
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                      MakeTuple(a, b));
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class A, class B, class C>
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method,
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const A& a, const B& b, const C& c) {
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                         MakeTuple(a, b, c));
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class A, class B, class C, class D>
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method,
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const A& a, const B& b,
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const C& c, const D& d) {
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                            MakeTuple(a, b,
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                                      c, d));
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class A, class B, class C, class D, class E>
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method,
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const A& a, const B& b,
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const C& c, const D& d, const E& e) {
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T,
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            Method,
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            Tuple5<A, B, C, D, E> >(object,
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                    method,
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                    MakeTuple(a, b, c, d, e));
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class A, class B, class C, class D, class E,
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          class F>
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method,
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const A& a, const B& b,
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const C& c, const D& d, const E& e,
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const F& f) {
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T,
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            Method,
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            Tuple6<A, B, C, D, E, F> >(object,
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                       method,
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                       MakeTuple(a, b, c, d, e,
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                                 f));
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T, class Method, class A, class B, class C, class D, class E,
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          class F, class G>
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableMethod(T* object, Method method,
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         const A& a, const B& b,
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         const C& c, const D& d, const E& e,
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         const F& f, const G& g) {
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableMethod<T,
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            Method,
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            Tuple7<A, B, C, D, E, F, G> >(object,
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                          method,
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                          MakeTuple(a, b, c, d,
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                                    e, f, g));
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// RunnableFunction and NewRunnableFunction implementation ---------------------
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class Function, class Params>
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass RunnableFunction : public CancelableTask {
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RunnableFunction(Function function, const Params& params)
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : function_(function), params_(params) {
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    COMPILE_ASSERT((FunctionUsesScopedRefptrCorrectly<Function, Params>::value),
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   badrunnablefunctionparams);
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~RunnableFunction() {
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run() {
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (function_)
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DispatchToFunction(function_, params_);
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Cancel() {
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Function function_;
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Params params_;
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class Function>
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableFunction(Function function) {
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableFunction<Function, Tuple0>(function, MakeTuple());
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class Function, class A>
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableFunction(Function function, const A& a) {
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class Function, class A, class B>
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableFunction(Function function,
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const A& a, const B& b) {
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableFunction<Function, Tuple2<A, B> >(function,
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                       MakeTuple(a, b));
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class Function, class A, class B, class C>
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableFunction(Function function,
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const A& a, const B& b,
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const C& c) {
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                          MakeTuple(a, b, c));
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class Function, class A, class B, class C, class D>
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableFunction(Function function,
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const A& a, const B& b,
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const C& c, const D& d) {
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                             MakeTuple(a, b,
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                                       c, d));
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class Function, class A, class B, class C, class D, class E>
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline CancelableTask* NewRunnableFunction(Function function,
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const A& a, const B& b,
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const C& c, const D& d,
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           const E& e) {
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                                MakeTuple(a, b,
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                                          c, d,
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                                          e));
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <class Function, class A, class B, class C, class D, class E,
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          class F>
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline CancelableTask* NewRunnableFunction(Function function,
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const A& a, const B& b,
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const C& c, const D& d,
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const E& e, const F& f) {
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new RunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function,
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MakeTuple(a, b, c, d, e, f));
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <class Function, class A, class B, class C, class D, class E,
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          class F, class G>
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline CancelableTask* NewRunnableFunction(Function function,
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const A& a, const B& b,
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const C& c, const D& d,
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const E& e, const F& f,
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const G& g) {
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new RunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(function,
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MakeTuple(a, b, c, d, e, f, g));
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <class Function, class A, class B, class C, class D, class E,
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          class F, class G, class H>
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline CancelableTask* NewRunnableFunction(Function function,
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const A& a, const B& b,
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const C& c, const D& d,
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const E& e, const F& f,
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           const G& g, const H& h) {
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new RunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >(
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      function, MakeTuple(a, b, c, d, e, f, g, h));
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // BASE_TASK_H_
526