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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
// Copyright (c) 2011 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 BASE_THREAD_H_
#define BASE_THREAD_H_
#pragma once
#include <string>
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/threading/platform_thread.h"
namespace base {
// A simple thread abstraction that establishes a MessageLoop on a new thread.
// The consumer uses the MessageLoop of the thread to cause code to execute on
// the thread. When this object is destroyed the thread is terminated. 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 Thread : PlatformThread::Delegate {
public:
struct Options {
Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
Options(MessageLoop::Type type, size_t size)
: message_loop_type(type), stack_size(size) {}
// Specifies the type of message loop that will be allocated on the thread.
MessageLoop::Type message_loop_type;
// Specifies the maximum stack size that the thread is allowed to use.
// This does not necessarily correspond to the thread's initial stack size.
// A value of 0 indicates that the default maximum should be used.
size_t stack_size;
};
// Constructor.
// name is a display string to identify the thread.
explicit Thread(const char* name);
// Destroys the thread, stopping it if necessary.
//
// NOTE: If you are subclassing from Thread, and you wish for your CleanUp
// method to be called, then you need to call Stop() from your destructor.
//
virtual ~Thread();
// Starts the thread. Returns true if the thread was successfully started;
// otherwise, returns false. Upon successful return, the message_loop()
// getter will return non-null.
//
// 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.
bool Start();
// Starts the thread. Behaves exactly like Start in addition to allow to
// override the default options.
//
// 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.
bool StartWithOptions(const Options& options);
// Signals the thread to exit and returns once the thread has exited. After
// this method returns, the Thread object is completely reset and may be used
// as if it were newly constructed (i.e., Start may be called again).
//
// Stop may be called multiple times and is simply ignored if the thread is
// already stopped.
//
// NOTE: This method is optional. It is not strictly necessary to call this
// method as the Thread's destructor will take care of stopping the thread if
// necessary.
//
void Stop();
// Signals the thread to exit in the near future.
//
// WARNING: This function is not meant to be commonly used. Use at your own
// risk. Calling this function will cause message_loop() to become invalid in
// the near future. This function was created to workaround a specific
// deadlock on Windows with printer worker thread. In any other case, Stop()
// should be used.
//
// StopSoon should not be called multiple times as it is risky to do so. It
// could cause a timing issue in message_loop() access. Call Stop() to reset
// the thread object once it is known that the thread has quit.
void StopSoon();
// Returns the message loop for this thread. Use the MessageLoop's
// PostTask methods to execute code on the thread. This only returns
// non-null after a successful call to Start. After Stop has been called,
// this will return NULL.
//
// NOTE: You must not call this MessageLoop's Quit method directly. Use
// the Thread's Stop method instead.
//
MessageLoop* message_loop() const { return message_loop_; }
// Returns a MessageLoopProxy for this thread. Use the MessageLoopProxy's
// PostTask methods to execute code on the thread. This only returns
// non-NULL after a successful call to Start. After Stop has been called,
// this will return NULL. Callers can hold on to this even after the thread
// is gone.
// TODO(sanjeevr): Look into merging MessageLoop and MessageLoopProxy.
scoped_refptr<MessageLoopProxy> message_loop_proxy() {
return message_loop_proxy_;
}
// Set the name of this thread (for display in debugger too).
const std::string &thread_name() { return name_; }
// The native thread handle.
PlatformThreadHandle thread_handle() { return thread_; }
// The thread ID.
PlatformThreadId thread_id() const { return thread_id_; }
// Returns true if the thread has been started, and not yet stopped.
// When a thread is running, |thread_id_| is a valid id.
bool IsRunning() const { return thread_id_ != kInvalidThreadId; }
protected:
// Called just prior to starting the message loop
virtual void Init() {}
// Called to start the message loop
virtual void Run(MessageLoop* message_loop);
// Called just after the message loop ends
virtual void CleanUp() {}
// Called after the message loop has been deleted. In general clients
// should prefer to use CleanUp(). This method is used when code needs to
// be run after all of the MessageLoop::DestructionObservers have completed.
virtual void CleanUpAfterMessageLoopDestruction() {}
static void SetThreadWasQuitProperly(bool flag);
static bool GetThreadWasQuitProperly();
void set_message_loop(MessageLoop* message_loop) {
message_loop_ = message_loop;
}
private:
bool thread_was_started() const { return started_; }
// PlatformThread::Delegate methods:
virtual void ThreadMain();
// Whether we successfully started the thread.
bool started_;
// If true, we're in the middle of stopping, and shouldn't access
// |message_loop_|. It may non-NULL and invalid.
bool stopping_;
// Used to pass data to ThreadMain.
struct StartupData;
StartupData* startup_data_;
// The thread's handle.
PlatformThreadHandle thread_;
// The thread's message loop. Valid only while the thread is alive. Set
// by the created thread.
MessageLoop* message_loop_;
// A MessageLoopProxy implementation that targets this thread. This can
// outlive the thread.
scoped_refptr<MessageLoopProxy> message_loop_proxy_;
// Our thread's ID.
PlatformThreadId thread_id_;
// The name of the thread. Used for debugging purposes.
std::string name_;
friend class ThreadQuitTask;
DISALLOW_COPY_AND_ASSIGN(Thread);
};
} // namespace base
#endif // BASE_THREAD_H_
|