OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 BASE_THREAD_H_ | |
6 #define BASE_THREAD_H_ | |
7 #pragma once | |
8 | |
9 #include <string> | |
10 | |
11 #include "base/message_loop.h" | |
12 #include "base/message_loop_proxy.h" | |
13 #include "base/threading/platform_thread.h" | |
14 | |
15 namespace base { | |
16 | |
17 // A simple thread abstraction that establishes a MessageLoop on a new thread. | |
18 // The consumer uses the MessageLoop of the thread to cause code to execute on | |
19 // the thread. When this object is destroyed the thread is terminated. All | |
20 // pending tasks queued on the thread's message loop will run to completion | |
21 // before the thread is terminated. | |
22 // | |
23 // After the thread is stopped, the destruction sequence is: | |
24 // | |
25 // (1) Thread::CleanUp() | |
26 // (2) MessageLoop::~MessageLoop | |
27 // (3.b) MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop | |
28 // (4) Thread::CleanUpAfterMessageLoopDestruction() | |
29 class Thread : PlatformThread::Delegate { | |
30 public: | |
31 struct Options { | |
32 // Specifies the type of message loop that will be allocated on the thread. | |
33 MessageLoop::Type message_loop_type; | |
34 | |
35 // Specifies the maximum stack size that the thread is allowed to use. | |
36 // This does not necessarily correspond to the thread's initial stack size. | |
37 // A value of 0 indicates that the default maximum should be used. | |
38 size_t stack_size; | |
39 | |
40 Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {} | |
41 Options(MessageLoop::Type type, size_t size) | |
42 : message_loop_type(type), stack_size(size) {} | |
43 }; | |
44 | |
45 // Constructor. | |
46 // name is a display string to identify the thread. | |
47 explicit Thread(const char* name); | |
48 | |
49 // Destroys the thread, stopping it if necessary. | |
50 // | |
51 // NOTE: If you are subclassing from Thread, and you wish for your CleanUp | |
52 // method to be called, then you need to call Stop() from your destructor. | |
53 // | |
54 virtual ~Thread(); | |
55 | |
56 // Starts the thread. Returns true if the thread was successfully started; | |
57 // otherwise, returns false. Upon successful return, the message_loop() | |
58 // getter will return non-null. | |
59 // | |
60 // Note: This function can't be called on Windows with the loader lock held; | |
61 // i.e. during a DllMain, global object construction or destruction, atexit() | |
62 // callback. | |
63 bool Start(); | |
64 | |
65 // Starts the thread. Behaves exactly like Start in addition to allow to | |
66 // override the default options. | |
67 // | |
68 // Note: This function can't be called on Windows with the loader lock held; | |
69 // i.e. during a DllMain, global object construction or destruction, atexit() | |
70 // callback. | |
71 bool StartWithOptions(const Options& options); | |
72 | |
73 // Signals the thread to exit and returns once the thread has exited. After | |
74 // this method returns, the Thread object is completely reset and may be used | |
75 // as if it were newly constructed (i.e., Start may be called again). | |
76 // | |
77 // Stop may be called multiple times and is simply ignored if the thread is | |
78 // already stopped. | |
79 // | |
80 // NOTE: This method is optional. It is not strictly necessary to call this | |
81 // method as the Thread's destructor will take care of stopping the thread if | |
82 // necessary. | |
83 // | |
84 void Stop(); | |
85 | |
86 // Signals the thread to exit in the near future. | |
87 // | |
88 // WARNING: This function is not meant to be commonly used. Use at your own | |
89 // risk. Calling this function will cause message_loop() to become invalid in | |
90 // the near future. This function was created to workaround a specific | |
91 // deadlock on Windows with printer worker thread. In any other case, Stop() | |
92 // should be used. | |
93 // | |
94 // StopSoon should not be called multiple times as it is risky to do so. It | |
95 // could cause a timing issue in message_loop() access. Call Stop() to reset | |
96 // the thread object once it is known that the thread has quit. | |
97 void StopSoon(); | |
98 | |
99 // Returns the message loop for this thread. Use the MessageLoop's | |
100 // PostTask methods to execute code on the thread. This only returns | |
101 // non-null after a successful call to Start. After Stop has been called, | |
102 // this will return NULL. | |
103 // | |
104 // NOTE: You must not call this MessageLoop's Quit method directly. Use | |
105 // the Thread's Stop method instead. | |
106 // | |
107 MessageLoop* message_loop() const { return message_loop_; } | |
108 | |
109 // Returns a MessageLoopProxy for this thread. Use the MessageLoopProxy's | |
110 // PostTask methods to execute code on the thread. This only returns | |
111 // non-NULL after a successful call to Start. After Stop has been called, | |
112 // this will return NULL. Callers can hold on to this even after the thread | |
113 // is gone. | |
114 // TODO(sanjeevr): Look into merging MessageLoop and MessageLoopProxy. | |
115 scoped_refptr<MessageLoopProxy> message_loop_proxy() { | |
116 return message_loop_proxy_; | |
117 } | |
118 | |
119 // Set the name of this thread (for display in debugger too). | |
120 const std::string &thread_name() { return name_; } | |
121 | |
122 // The native thread handle. | |
123 PlatformThreadHandle thread_handle() { return thread_; } | |
124 | |
125 // The thread ID. | |
126 PlatformThreadId thread_id() const { return thread_id_; } | |
127 | |
128 // Returns true if the thread has been started, and not yet stopped. | |
129 // When a thread is running, |thread_id_| is a valid id. | |
130 bool IsRunning() const { return thread_id_ != kInvalidThreadId; } | |
131 | |
132 protected: | |
133 // Called just prior to starting the message loop | |
134 virtual void Init() {} | |
135 | |
136 // Called to start the message loop | |
137 virtual void Run(MessageLoop* message_loop); | |
138 | |
139 // Called just after the message loop ends | |
140 virtual void CleanUp() {} | |
141 | |
142 // Called after the message loop has been deleted. In general clients | |
143 // should prefer to use CleanUp(). This method is used when code needs to | |
144 // be run after all of the MessageLoop::DestructionObservers have completed. | |
145 virtual void CleanUpAfterMessageLoopDestruction() {} | |
146 | |
147 static void SetThreadWasQuitProperly(bool flag); | |
148 static bool GetThreadWasQuitProperly(); | |
149 | |
150 void set_message_loop(MessageLoop* message_loop) { | |
151 message_loop_ = message_loop; | |
152 } | |
153 | |
154 private: | |
155 // PlatformThread::Delegate methods: | |
156 virtual void ThreadMain(); | |
157 | |
158 bool thread_was_started() const { return started_; } | |
159 | |
160 // Whether we successfully started the thread. | |
161 bool started_; | |
162 | |
163 // If true, we're in the middle of stopping, and shouldn't access | |
164 // |message_loop_|. It may non-NULL and invalid. | |
165 bool stopping_; | |
166 | |
167 // Used to pass data to ThreadMain. | |
168 struct StartupData; | |
169 StartupData* startup_data_; | |
170 | |
171 // The thread's handle. | |
172 PlatformThreadHandle thread_; | |
173 | |
174 // The thread's message loop. Valid only while the thread is alive. Set | |
175 // by the created thread. | |
176 MessageLoop* message_loop_; | |
177 | |
178 // A MessageLoopProxy implementation that targets this thread. This can | |
179 // outlive the thread. | |
180 scoped_refptr<MessageLoopProxy> message_loop_proxy_; | |
181 | |
182 // Our thread's ID. | |
183 PlatformThreadId thread_id_; | |
184 | |
185 // The name of the thread. Used for debugging purposes. | |
186 std::string name_; | |
187 | |
188 friend class ThreadQuitTask; | |
189 | |
190 DISALLOW_COPY_AND_ASSIGN(Thread); | |
191 }; | |
192 | |
193 } // namespace base | |
194 | |
195 #endif // BASE_THREAD_H_ | |
OLD | NEW |