LCOV - code coverage report
Current view: top level - cppthread - runner.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 52 1.9 %
Date: 2021-08-21 09:27:22 Functions: 2 12 16.7 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13