summaryrefslogtreecommitdiffstats
path: root/remoting/base/auto_thread.h
blob: ece36856227cf0a7b3cfe9621ea5ac3f99fab457 (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 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_H_
#define REMOTING_BASE_AUTO_THREAD_H_

#include <string>

#include "base/message_loop/message_loop.h"
#include "base/threading/platform_thread.h"
#include "remoting/base/auto_thread_task_runner.h"

namespace remoting {

// Thread implementation that runs a MessageLoop on a new thread, and manages
// the lifetime of the MessageLoop and thread by tracking references to the
// thread's TaskRunner.  The caller passes the thread's TaskRunner to each
// object that needs to run code on the thread, and when no references to the
// TaskRunner remain, the thread will exit.  When the caller destroys this
// object they will be blocked until the thread exits.
// All pending tasks queued on the thread's message loop will run to completion
// before the thread is terminated.
//
// After the thread is stopped, the destruction sequence is:
//
//  (1) Thread::CleanUp()
//  (2) MessageLoop::~MessageLoop
//  (3.b)    MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop
class AutoThread : base::PlatformThread::Delegate {
 public:
  // Create an AutoThread with the specified message-loop |type| and |name|.
  // The supplied AutoThreadTaskRunner will be used to join and delete the
  // new thread when no references to it remain.
  static scoped_refptr<AutoThreadTaskRunner> CreateWithType(
      const char* name,
      scoped_refptr<AutoThreadTaskRunner> joiner,
      base::MessageLoop::Type type);
  static scoped_refptr<AutoThreadTaskRunner> Create(
      const char* name,
      scoped_refptr<AutoThreadTaskRunner> joiner);

#if defined(OS_WIN)
  // Create an AutoThread initialized for COM.  |com_init_type| specifies the
  // type of COM apartment to initialize.
  enum ComInitType { COM_INIT_NONE, COM_INIT_STA, COM_INIT_MTA };
  static scoped_refptr<AutoThreadTaskRunner> CreateWithLoopAndComInitTypes(
      const char* name,
      scoped_refptr<AutoThreadTaskRunner> joiner,
      base::MessageLoop::Type loop_type,
      ComInitType com_init_type);
#endif

  // Construct the AutoThread.  |name| identifies the thread for debugging.
  explicit AutoThread(const char* name);

  // Waits for the thread to exit, and then destroys it.
  virtual ~AutoThread();

  // Starts the thread, running the specified type of MessageLoop.  Returns
  // an AutoThreadTaskRunner through which tasks may be posted to the thread
  // if successful, or NULL on failure.
  //
  // Note: This function can't be called on Windows with the loader lock held;
  // i.e. during a DllMain, global object construction or destruction, atexit()
  // callback.
  //
  // NOTE: You must not call this MessageLoop's Quit method directly.  The
  // thread will exit when no references to the TaskRunner remain.
  scoped_refptr<AutoThreadTaskRunner> StartWithType(
      base::MessageLoop::Type type);

#if defined(OS_WIN)
  // Configures the thread to initialize the specified COM apartment type.
  // SetComInitType() must be called before Start().
  void SetComInitType(ComInitType com_init_type);
#endif

 private:
  AutoThread(const char* name, AutoThreadTaskRunner* joiner);

  void QuitThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  void JoinAndDeleteThread();

  // base::PlatformThread::Delegate methods:
  virtual void ThreadMain() override;

  // Used to pass data to ThreadMain.
  struct StartupData;
  StartupData* startup_data_;

#if defined(OS_WIN)
  // Specifies which kind of COM apartment to initialize, if any.
  ComInitType com_init_type_;
#endif

  // The thread's handle.
  base::PlatformThreadHandle thread_;

  // The name of the thread.  Used for debugging purposes.
  std::string name_;

  // Flag used to indicate whether MessageLoop was quit properly.
  // This allows us to detect premature exit via MessageLoop::Quit().
  bool was_quit_properly_;

  // AutoThreadTaskRunner to post a task to to join & delete this thread.
  scoped_refptr<AutoThreadTaskRunner> joiner_;

  DISALLOW_COPY_AND_ASSIGN(AutoThread);
};

}  // namespace remoting

#endif  // REMOTING_AUTO_THREAD_H_