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