1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file.
4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#ifndef CC_TREES_BLOCKING_TASK_RUNNER_H_
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define CC_TREES_BLOCKING_TASK_RUNNER_H_
7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <vector>
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/location.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/scoped_ptr.h"
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/single_thread_task_runner.h"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/synchronization/lock.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/threading/platform_thread.h"
15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "cc/base/cc_export.h"
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace cc {
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// This class wraps a SingleThreadTaskRunner but allows posted tasks to be
20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// run without a round trip through the message loop. This shortcutting
21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// removes guarantees about ordering. Tasks posted while the
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// BlockingTaskRunner is in a capturing state will run in order, and tasks
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// posted while the BlockingTaskRunner is /not/ in a capturing state will
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// run in order, but the two sets of tasks will *not* run in order relative
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// to when they were posted.
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)//
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// To use this class, post tasks to the task runner returned by
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// BlockingTaskRunner::Create(). The thread it is created on identifies the
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// thread you want the tasks to run on. The SingleThreadTaskRunner which is
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// passed into Create() is used to run tasks that are posted when not in a
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// capturing state.
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)//
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Then, on the thread that the given task runner belongs to, you may
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// instantiate a BlockingTaskRunner::CapturePostTasks. While this object
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// exists, the task runner will collect any PostTasks called on it, posting
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// tasks to that thread from anywhere. This CapturePostTasks object provides
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// a window in time where tasks can shortcut past the MessageLoop. As soon
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// as the CapturePostTasks object is destroyed (goes out of scope), all
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// tasks that had been posted to the thread during the window will be executed
40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// immediately.
41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)//
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Beware of re-entrancy, make sure the CapturePostTasks object is destroyed at
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// a time when it makes sense for the embedder to call arbitrary things.
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass CC_EXPORT BlockingTaskRunner {
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) public:
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Creates a BlockingTaskRunner for a given SingleThreadTaskRunner.
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // |task_runner| will be used to run the tasks which are posted while we are
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // not capturing. |task_runner| should belong to same the thread on which
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // capturing is done.
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static scoped_ptr<BlockingTaskRunner> Create(
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ~BlockingTaskRunner();
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // While an object of this type is held alive on a thread, any tasks
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // posted to the thread will be captured and run as soon as the object
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // is destroyed, shortcutting past the task runner.
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  class CC_EXPORT CapturePostTasks {
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)   public:
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    explicit CapturePostTasks(BlockingTaskRunner* blocking_runner);
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ~CapturePostTasks();
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)   private:
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BlockingTaskRunner* blocking_runner_;
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(CapturePostTasks);
67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  };
68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // True if tasks posted to the BlockingTaskRunner will run on the current
70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // thread.
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool BelongsToCurrentThread();
72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Posts a task using the contained SingleThreadTaskRunner unless |capture_|
74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // is true. When |capture_| is true, tasks posted will be caught and stored
75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // until the capturing stops. At that time the tasks will be run directly
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // instead of being posted to the SingleThreadTaskRunner.
77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bool PostTask(const tracked_objects::Location& from_here,
78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                const base::Closure& task);
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private:
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  explicit BlockingTaskRunner(
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  void SetCapture(bool capture);
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::PlatformThreadId thread_id_;
87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::Lock lock_;
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int capture_;
91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::vector<base::Closure> captured_tasks_;
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(BlockingTaskRunner);
94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)};
95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace cc
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif  // CC_TREES_BLOCKING_TASK_RUNNER_H_
99