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