Line data Source code
1 : // Copyright (c) 2013-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/cppthread
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : /** \file
21 : * \brief Implementation of the Thread Runner and Managers.
22 : *
23 : * This file includes the implementation used by the cppthread environment.
24 : */
25 :
26 :
27 : // self
28 : //
29 : #include "cppthread/runner.h"
30 :
31 : #include "cppthread/guard.h"
32 : #include "cppthread/log.h"
33 : #include "cppthread/thread.h"
34 :
35 :
36 : // last include
37 : //
38 : #include <snapdev/poison.h>
39 :
40 :
41 :
42 :
43 : namespace cppthread
44 : {
45 :
46 :
47 :
48 : /** \brief Initializes the runner.
49 : *
50 : * The constructor expects a name. The name is mainly used in case a
51 : * problem occur and we want to log a message. That way you will know
52 : * which thread runner caused a problem.
53 : *
54 : * \note
55 : * The first 15 characters of the name are also used to set the thread
56 : * name with the pthread_setname_np() and set_current_thread_name()
57 : * functions. That name is then available in the
58 : * `/proc/self/task/<tid>/comm` file, which is useful as such a name will
59 : * appear in the output of ps and htop and other such tools.
60 : *
61 : * See: https://stackoverflow.com/questions/68676407/how-do-i-change-the-name-of-one-singlre-thread-in-linux#68676407
62 : *
63 : * \param[in] name The name of this thread runner.
64 : */
65 0 : runner::runner(std::string const & name)
66 0 : : f_name(name)
67 : {
68 : // TBD: should we forbid starting a runner without a name?
69 : //
70 0 : if(!name.empty())
71 : {
72 : // make sure to limit the name to 15 characters
73 : //
74 0 : std::string const name15(f_name.substr(0, 15));
75 :
76 : // the pthread_setname_np() allows for the name to be retrieved
77 : // with its counter part:
78 : //
79 : // pthread_getname_np()
80 : //
81 0 : pthread_setname_np(pthread_self(), name15.c_str());
82 :
83 : // but to really change the name in the comm file (and therefore
84 : // htop, ps, etc.) we further call the set_current_thread_name()
85 : // function
86 : //
87 0 : set_current_thread_name(name15);
88 : }
89 0 : }
90 :
91 :
92 : /** \brief The destructor checks that the thread was stopped.
93 : *
94 : * This function verifies that the thread was stopped before the
95 : * object gets destroyed (and is likely to break something along
96 : * the way.)
97 : */
98 0 : runner::~runner()
99 : {
100 : // the thread should never be set when the runner gets deleted
101 0 : if(f_thread)
102 : {
103 : // this is a bug; it could be that the object that derived from
104 : // the snap_runner calls gets destroyed under the thread controller's
105 : // nose and that could break a lot of things.
106 0 : log << log_level_t::fatal
107 0 : << "The Snap! thread runner named \""
108 0 : << f_name
109 0 : << "\" is still marked as running when its object is being destroyed."
110 0 : << end;
111 0 : std::terminate();
112 : }
113 0 : }
114 :
115 :
116 : /** \brief Retrieve the name of the runner.
117 : *
118 : * This function returns the name of the runner as specified in the
119 : * constructor.
120 : *
121 : * Since the name is read-only, it will always match one to one what
122 : * you passed on.
123 : *
124 : * \return The name of this thread runner.
125 : */
126 0 : std::string const & runner::get_name() const
127 : {
128 0 : return f_name;
129 : }
130 :
131 :
132 : /** \brief Check whether this thread runner is ready.
133 : *
134 : * By default a thread runner is considered ready. If you reimplement this
135 : * function it is possible to tell the thread controller that you are not
136 : * ready. This means the start() function will fail and return false.
137 : *
138 : * \return true by default, can return false to prevent a start() command.
139 : */
140 0 : bool runner::is_ready() const
141 : {
142 0 : return true;
143 : }
144 :
145 :
146 : /** \brief Whether the thread should continue running.
147 : *
148 : * This function checks whether the user who handles the controller asked
149 : * the thread to quit. If so, then the function returns false. If not
150 : * the function returns true.
151 : *
152 : * The function can be reimplemented in your runner. In that case, the
153 : * runner implementation should probably call this function too in order
154 : * to make sure that the stop() function works.
155 : *
156 : * It is expected that your run() function implements a loop that checks
157 : * this flag on each iteration with iterations that take as little time
158 : * as possible.
159 : *
160 : * \code
161 : * void my_runner::run()
162 : * {
163 : * while(continue_running())
164 : * {
165 : * // do some work
166 : * ...
167 : * }
168 : * }
169 : * \endcode
170 : *
171 : * \return true if the thread is expected to continue running.
172 : */
173 0 : bool runner::continue_running() const
174 : {
175 0 : guard lock(f_mutex);
176 0 : if(f_thread == nullptr)
177 : {
178 0 : return true;
179 : }
180 0 : return !f_thread->is_stopping();
181 : }
182 :
183 :
184 : /** \brief Signal that the run() function is about to be entered.
185 : *
186 : * This function is often used as a way to initialize the thread runner.
187 : * The default is to log the fact that the thread is being started. You
188 : * often call it at the start of your enter() implementation.
189 : *
190 : * The reason for heaving a separate enter() and leave() pair of functions
191 : * is to help with the possibility that your run() function throws and is
192 : * not waited on. If the \em parent thread is working on something else
193 : * or waiting on a different thread, then you would have no idea that the
194 : * thread is ending.
195 : *
196 : * \attention
197 : * The enter() will always be called, but the run() and leave() functions
198 : * do not get called if a preceeding call ends in an abnormal manner (i.e.
199 : * such as emitting an abort() call, a SEGV, etc.) Exceptions are properly
200 : * handled, however, if the enter() function exits with an exception, then
201 : * the run() function doesn't get called.
202 : */
203 0 : void runner::enter()
204 : {
205 : // there is a mutex lock in the get_thread_tid() so try to avoid a
206 : // potential deadlock by getting the value ahead
207 : //
208 0 : pid_t const tid(f_thread->get_thread_tid());
209 :
210 0 : log << log_level_t::info
211 0 : << "entering thread \""
212 0 : << get_name()
213 0 : << "\" #"
214 0 : << tid
215 0 : << "."
216 0 : << end;
217 0 : }
218 :
219 :
220 : /** \brief Signal that the run() function has returned.
221 : *
222 : * This function is called whenever the run() function is done. It may also
223 : * be called if the enter() function throws in which case the run() function
224 : * does not get called but the leave() function still gets called.
225 : *
226 : * This function is useful to know that the run() function returned without
227 : * you having to instrument your run() function with a try/catch. This is
228 : * particularly useful to detect that a thread died when not expected.
229 : * Specifically, if your \em parent thread is not activelly waiting on
230 : * your thread demise, the fact that the run() function threw an exception
231 : * will not be known until later if ever. The leave() function can act in
232 : * such a way that the \em parent thread is then aware of the issue and
233 : * either quits, restarts the thread, or just reports the issue.
234 : *
235 : * The \p status parameter defines which location the leave() function is
236 : * called from. It can be called in the following cases:
237 : *
238 : * * LEAVE_STATUS_NORMAL -- the enter() and run() functions worked as expected.
239 : * * LEAVE_STATUS_INITIALIZATION_FAILED -- the enter() function failed with
240 : * an exception; the run() function was never called.
241 : * * LEAVE_STATUS_THREAD_FAILED -- the run() function was called and it
242 : * generated an exception.
243 : * * LEAVE_STATUS_INSTRUMENTATION -- a function, other than the enter() or
244 : * run() functions, generated an error.
245 : *
246 : * The default function logs the fact that the thread is exiting. You often
247 : * call it at the end of your own leave() implementation.
248 : *
249 : * \param[in] status The location from which the leave() function get called.
250 : */
251 0 : void runner::leave(leave_status_t status)
252 : {
253 : // there is a mutex lock in the get_thread_tid() so try to avoid a
254 : // potential deadlock by getting the value ahead
255 : //
256 0 : pid_t const tid(f_thread->get_thread_tid());
257 :
258 0 : log << log_level_t::info
259 0 : << "leaving thread \""
260 0 : << get_name()
261 0 : << "\" #"
262 0 : << tid
263 0 : << " with status "
264 0 : << static_cast<int>(status) // TODO: write name too
265 0 : << "."
266 0 : << end;
267 0 : }
268 :
269 :
270 : /** \brief Retrieve the thread controller linked to this runner.
271 : *
272 : * Each runner is assigned a thread controller whenever the thread
273 : * is created (they get attached, in effect.) Once the thread is
274 : * destroyed, the pointer goes back to nullptr.
275 : *
276 : * \return A thread pointer or nullptr.
277 : */
278 0 : thread * runner::get_thread() const
279 : {
280 0 : return f_thread;
281 : }
282 :
283 :
284 : /** \brief Get this runner thread identifier.
285 : *
286 : * This function returns the thread identifier of the thread running
287 : * this runner run() function.
288 : *
289 : * This function can be called from any thread and the correct value
290 : * will be returned.
291 : *
292 : * \return The thread identifier.
293 : */
294 0 : pid_t runner::gettid() const
295 : {
296 0 : return f_thread->get_thread_tid();
297 : }
298 :
299 :
300 :
301 : /** \class runner
302 : * \brief The runner is the class that wraps the actual system thread.
303 : *
304 : * This class defines the actual thread wrapper. This is very important
305 : * because when the main thread object gets destroyed and if it
306 : * were a system thread, the virtual tables would be destroyed and thus
307 : * invalid before you reached the ~thread() destructor. This means
308 : * any of the virtual functions could not get called.
309 : *
310 : * For this reason we have a two level thread objects implementation:
311 : * the thread which acts as a controller and the snap_runner which
312 : * is the object that is the actual system thread and thus which has the
313 : * run() virtual function: the function that gets called when the thread
314 : * starts running.
315 : */
316 :
317 :
318 : /** \typedef runner::pointer_t
319 : * \brief The shared pointer of a thread runner.
320 : *
321 : * This type is used to hold a smart pointer to a thread runner.
322 : *
323 : * Be very careful. Using a smart pointer does NOT mean that you can just
324 : * delete a snap_runner without first stopping the thread. Make sure to
325 : * have a thread object to manage your snap_running pointers (i.e you
326 : * can delete a thread, which will stop your snap_runner and then
327 : * delete the snap_runner.)
328 : */
329 :
330 :
331 : /** \typedef runner::vector_t
332 : * \brief A vector of threads.
333 : *
334 : * This type defines a vector of thread runners as used by the
335 : * cppthread::thread_pool template.
336 : *
337 : * Be careful as vectors are usually copyable and this one is because it
338 : * holds smart pointers to thread runners, not the actual thread. You
339 : * still only have one thread, just multiple instances of its pointer.
340 : * However, keep in mind that you can't just destroy a runner. The
341 : * thread it is runner must be stopped first. Please make sure to
342 : * have a thread or a thread::pool to manage
343 : * your thread runners.
344 : */
345 :
346 :
347 : /** \enum leave_status_t
348 : * \brief The exit status.
349 : *
350 : * When the runner exits, the run() function saves the status of how the
351 : * function exited. It can be useful to know how the run() function exited
352 : * to decide on how to react.
353 : */
354 :
355 :
356 : /** \var runner::f_mutex
357 : * \brief The mutex of this thread.
358 : *
359 : * Each thread is given its own mutex so it can handle its data safely.
360 : *
361 : * This mutex is expected to mainly be used by the thread and its parent.
362 : *
363 : * If you want to share data and mutexes between multiple threads,
364 : * you may want to consider using another mutex. For example, the
365 : * cppthread::fifo is itself derived from the mutex
366 : * class. So when you use a FIFO between multiple threads, the
367 : * lock/unlock mechanism is not using the mutex of your thread.
368 : */
369 :
370 :
371 : /** \var runner::f_thread
372 : * \brief A pointer back to the owner ("parent") of this runner
373 : *
374 : * When a snap_runner is created, it gets created by a specific \em parent
375 : * object. This pointer holds that parent.
376 : *
377 : * The runner uses this pointer to know whether it is still running
378 : * and to retrieve its identifier that the parent holds.
379 : */
380 :
381 :
382 : /** \var runner::f_name
383 : * \brief The name of this thread.
384 : *
385 : * Each thread is given a name. This can help greatly when debugging a
386 : * threaded environment with a large number of threads. That way you
387 : * can easily identify which thread did what and work you way to a
388 : * perfect software.
389 : *
390 : * On some systems it may be possible to give this name to the OS
391 : * which then can be displayed in tools listing processes and threads.
392 : */
393 :
394 :
395 : /** \fn runner::runner(runner const & rhs);
396 : * \brief The copy operator is deleted.
397 : *
398 : * A runner represents a running thread which is pretty much impossible to
399 : * copy so we prevent such of the class too.
400 : *
401 : * \param[in] rhs The right hand side.
402 : */
403 :
404 :
405 : /** \fn runner::operator = (runner const & rhs);
406 : * \brief This assignment operator is deleted.
407 : *
408 : * A runner represents a running thread which is pretty much impossible to
409 : * copy so we prevent such of the class too.
410 : *
411 : * \param[in] rhs The right hand side.
412 : *
413 : * \return A reference to this object.
414 : */
415 :
416 :
417 : /** \fn runner::run();
418 : * \brief This virtual function represents the code run by the thread.
419 : *
420 : * The run() function is the one you have to implement in order to have
421 : * something to execute when the thread is started.
422 : *
423 : * To exit the thread, simply return from the run() function.
424 : */
425 :
426 :
427 :
428 :
429 6 : } // namespace cppthread
430 : // vim: ts=4 sw=4 et
|