summaryrefslogtreecommitdiffstats
path: root/remoting/base/auto_thread_task_runner.h
blob: bc4fd7cf175e253ce36a24b843c4cf9daccab84a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_BASE_AUTO_THREAD_TASK_RUNNER_H_
#define REMOTING_BASE_AUTO_THREAD_TASK_RUNNER_H_

#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/single_thread_task_runner.h"

class MessageLoop;

namespace remoting {

// A wrapper around |SingleThreadTaskRunner| that provides automatic lifetime
// management, by invoking a caller-supplied callback when no more references
// remain, that can stop the wrapped task runner. The caller may also provide a
// reference to a parent |AutoThreadTaskRunner| to express dependencies between
// child and parent thread lifetimes.
class AutoThreadTaskRunner : public base::SingleThreadTaskRunner {
 public:
  // Constructs an instance of |AutoThreadTaskRunner| wrapping |task_runner|.
  // |stop_callback| is called (on arbitraty thread) when the last reference to
  // the object is dropped.
  explicit AutoThreadTaskRunner(
      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  AutoThreadTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                       const base::Closure& stop_callback);

  // TODO(alexeypa): Remove the |parent| reference once Thread class supports
  // stopping the thread's message loop and joining the thread separately.
  // See http://crbug.com/145856.
  //
  // Background: currently the only legitimate way of stopping a thread is to
  // call Thread::Stop() from the same thread that started it. Thread::Stop()
  // will stop the thread message loop by posting a private task and join
  // the thread. Thread::Stop() verifies that it is called from the right thread
  // and that the message loop has been stopped by the private task mentioned
  // above.
  //
  // Due to NPAPI/PPAPI limitations tasks cannot be posted to the main message
  // loop when the host plugin is being shut down. This presents a challenge
  // since Thread::Stop() cannot be called from an arbitrary thread. To work
  // around this we keep a reference to the parent task runner (typically
  // the one that started the thread) to keep it alive while the worker thread
  // is in use. Thread::Stop() is called to stop the worker thread when
  // the parent task runner exits.
  AutoThreadTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                       scoped_refptr<AutoThreadTaskRunner> parent);
  AutoThreadTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                       scoped_refptr<AutoThreadTaskRunner> parent,
                       const base::Closure& stop_callback);

  // SingleThreadTaskRunner implementation
  virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
                               const base::Closure& task,
                               base::TimeDelta delay) OVERRIDE;
  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task,
      base::TimeDelta delay) OVERRIDE;
  virtual bool RunsTasksOnCurrentThread() const OVERRIDE;

 private:
  friend class base::DeleteHelper<AutoThreadTaskRunner>;

  virtual ~AutoThreadTaskRunner();

  // An reference to the parent message loop to keep it alive while
  // |task_runner_| is running.
  scoped_refptr<AutoThreadTaskRunner> parent_;

  // This callback quits |task_runner_|. It can be run on any thread.
  base::Closure stop_callback_;

  // The wrapped task runner.
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  DISALLOW_COPY_AND_ASSIGN(AutoThreadTaskRunner);
};

}  // namespace remoting

#endif  // REMOTING_BASE_AUTO_THREAD_TASK_RUNNER_H_