1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef REMOTING_BASE_AUTO_THREAD_H_
6#define REMOTING_BASE_AUTO_THREAD_H_
7
8#include <string>
9
10#include "base/message_loop/message_loop.h"
11#include "base/threading/platform_thread.h"
12#include "remoting/base/auto_thread_task_runner.h"
13
14namespace remoting {
15
16// Thread implementation that runs a MessageLoop on a new thread, and manages
17// the lifetime of the MessageLoop and thread by tracking references to the
18// thread's TaskRunner.  The caller passes the thread's TaskRunner to each
19// object that needs to run code on the thread, and when no references to the
20// TaskRunner remain, the thread will exit.  When the caller destroys this
21// object they will be blocked until the thread exits.
22// All pending tasks queued on the thread's message loop will run to completion
23// before the thread is terminated.
24//
25// After the thread is stopped, the destruction sequence is:
26//
27//  (1) Thread::CleanUp()
28//  (2) MessageLoop::~MessageLoop
29//  (3.b)    MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop
30class AutoThread : base::PlatformThread::Delegate {
31 public:
32  // Create an AutoThread with the specified message-loop |type| and |name|.
33  // The supplied AutoThreadTaskRunner will be used to join and delete the
34  // new thread when no references to it remain.
35  static scoped_refptr<AutoThreadTaskRunner> CreateWithType(
36      const char* name,
37      scoped_refptr<AutoThreadTaskRunner> joiner,
38      base::MessageLoop::Type type);
39  static scoped_refptr<AutoThreadTaskRunner> Create(
40      const char* name,
41      scoped_refptr<AutoThreadTaskRunner> joiner);
42
43#if defined(OS_WIN)
44  // Create an AutoThread initialized for COM.  |com_init_type| specifies the
45  // type of COM apartment to initialize.
46  enum ComInitType { COM_INIT_NONE, COM_INIT_STA, COM_INIT_MTA };
47  static scoped_refptr<AutoThreadTaskRunner> CreateWithLoopAndComInitTypes(
48      const char* name,
49      scoped_refptr<AutoThreadTaskRunner> joiner,
50      base::MessageLoop::Type loop_type,
51      ComInitType com_init_type);
52#endif
53
54  // Construct the AutoThread.  |name| identifies the thread for debugging.
55  explicit AutoThread(const char* name);
56
57  // Waits for the thread to exit, and then destroys it.
58  virtual ~AutoThread();
59
60  // Starts the thread, running the specified type of MessageLoop.  Returns
61  // an AutoThreadTaskRunner through which tasks may be posted to the thread
62  // if successful, or NULL on failure.
63  //
64  // Note: This function can't be called on Windows with the loader lock held;
65  // i.e. during a DllMain, global object construction or destruction, atexit()
66  // callback.
67  //
68  // NOTE: You must not call this MessageLoop's Quit method directly.  The
69  // thread will exit when no references to the TaskRunner remain.
70  scoped_refptr<AutoThreadTaskRunner> StartWithType(
71      base::MessageLoop::Type type);
72
73#if defined(OS_WIN)
74  // Configures the thread to initialize the specified COM apartment type.
75  // SetComInitType() must be called before Start().
76  void SetComInitType(ComInitType com_init_type);
77#endif
78
79 private:
80  AutoThread(const char* name, AutoThreadTaskRunner* joiner);
81
82  void QuitThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
83  void JoinAndDeleteThread();
84
85  // base::PlatformThread::Delegate methods:
86  virtual void ThreadMain() OVERRIDE;
87
88  // Used to pass data to ThreadMain.
89  struct StartupData;
90  StartupData* startup_data_;
91
92#if defined(OS_WIN)
93  // Specifies which kind of COM apartment to initialize, if any.
94  ComInitType com_init_type_;
95#endif
96
97  // The thread's handle.
98  base::PlatformThreadHandle thread_;
99
100  // The name of the thread.  Used for debugging purposes.
101  std::string name_;
102
103  // Flag used to indicate whether MessageLoop was quit properly.
104  // This allows us to detect premature exit via MessageLoop::Quit().
105  bool was_quit_properly_;
106
107  // AutoThreadTaskRunner to post a task to to join & delete this thread.
108  scoped_refptr<AutoThreadTaskRunner> joiner_;
109
110  DISALLOW_COPY_AND_ASSIGN(AutoThread);
111};
112
113}  // namespace remoting
114
115#endif  // REMOTING_AUTO_THREAD_H_
116