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