cppthread 1.1.16
C++ Thread Library
Public Types | Public Member Functions | Protected Attributes | Private Attributes | Friends | List of all members
cppthread::runner Class Referenceabstract

The runner is the class that wraps the actual system thread. More...

Inheritance diagram for cppthread::runner:
Inheritance graph
[legend]
Collaboration diagram for cppthread::runner:
Collaboration graph
[legend]

Public Types

typedef std::shared_ptr< runnerpointer_t
 The shared pointer of a thread runner.
 
typedef std::vector< pointer_tvector_t
 A vector of threads.
 

Public Member Functions

 runner (runner const &rhs)=delete
 The copy operator is deleted.
 
 runner (std::string const &name)
 Initializes the runner.
 
virtual ~runner ()
 The destructor checks that the thread was stopped.
 
virtual bool continue_running () const
 Whether the thread should continue running.
 
virtual void enter ()
 Signal that the run() function is about to be entered.
 
std::string const & get_name () const
 Retrieve the name of the runner.
 
threadget_thread () const
 Retrieve the thread controller linked to this runner.
 
pid_t gettid () const
 Get this runner thread identifier.
 
virtual bool is_ready () const
 Check whether this thread runner is ready.
 
virtual void leave (leave_status_t status)
 Signal that the run() function has returned.
 
runneroperator= (runner const &rhs)=delete
 This assignment operator is deleted.
 
virtual void run ()=0
 This virtual function represents the code run by the thread.
 

Protected Attributes

mutex f_mutex = mutex()
 The mutex of this thread.
 

Private Attributes

std::string const f_name = std::string()
 The name of this thread.
 
threadf_thread = nullptr
 A pointer back to the owner ("parent") of this runner.
 

Friends

class thread
 Give access to the f_thread field.
 

Detailed Description

This class defines the actual thread wrapper. This is very important because when the main thread object gets destroyed and if it were a system thread, the virtual tables would be destroyed and thus invalid before you reached the ~thread() destructor. This means any of the virtual functions could not get called.

For this reason we have a two level thread objects implementation: the thread which acts as a controller and the snap_runner which is the object that is the actual system thread and thus which has the run() virtual function: the function that gets called when the thread starts running.

Definition at line 64 of file runner.h.

Member Typedef Documentation

◆ pointer_t

This type is used to hold a smart pointer to a thread runner.

Be very careful. Using a smart pointer does NOT mean that you can just delete a snap_runner without first stopping the thread. Make sure to have a thread object to manage your snap_running pointers (i.e you can delete a thread, which will stop your snap_runner and then delete the snap_runner.)

Definition at line 67 of file runner.h.

◆ vector_t

This type defines a vector of thread runners as used by the cppthread::thread_pool template.

Be careful as vectors are usually copyable and this one is because it holds smart pointers to thread runners, not the actual thread. You still only have one thread, just multiple instances of its pointer. However, keep in mind that you can't just destroy a runner. The thread it is runner must be stopped first. Please make sure to have a thread or a thread::pool to manage your thread runners.

Definition at line 68 of file runner.h.

Constructor & Destructor Documentation

◆ runner() [1/2]

cppthread::runner::runner ( std::string const &  name)

The constructor expects a name. The name is mainly used in case a problem occur and we want to log a message. That way you will know which thread runner caused a problem.

Note
The first 15 characters of the name are also used to set the thread name with the pthread_setname_np() and set_current_thread_name() functions. That name is then available in the /proc/self/task/<tid>/comm file, which is useful as such a name will appear in the output of ps and htop and other such tools.

See: https://stackoverflow.com/questions/68676407/how-do-i-change-the-name-of-one-singlre-thread-in-linux#68676407

Parameters
[in]nameThe name of this thread runner.

Definition at line 65 of file runner.cpp.

◆ runner() [2/2]

cppthread::runner::runner ( runner const &  rhs)
delete

A runner represents a running thread which is pretty much impossible to copy so we prevent such of the class too.

Parameters
[in]rhsThe right hand side.

◆ ~runner()

cppthread::runner::~runner ( )
virtual

This function verifies that the thread was stopped before the object gets destroyed (and is likely to break something along the way.)

Definition at line 78 of file runner.cpp.

References cppthread::end(), f_name, f_thread, and cppthread::log.

Here is the call graph for this function:

Member Function Documentation

◆ continue_running()

bool cppthread::runner::continue_running ( ) const
virtual

This function checks whether the user who handles the controller asked the thread to quit. If so, then the function returns false. If not the function returns true.

The function can be reimplemented in your runner. In that case, the runner implementation should probably call this function too in order to make sure that the stop() function works.

It is expected that your run() function implements a loop that checks this flag on each iteration with iterations that take as little time as possible.

void my_runner::run()
{
{
// do some work
...
}
}
virtual bool continue_running() const
Whether the thread should continue running.
Definition runner.cpp:153
Returns
true if the thread is expected to continue running.

Definition at line 153 of file runner.cpp.

References f_mutex, f_thread, and cppthread::thread::is_stopping().

Referenced by cppthread::worker< T >::run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ enter()

void cppthread::runner::enter ( )
virtual

This function is often used as a way to initialize the thread runner. The default is to log the fact that the thread is being started. You often call it at the start of your enter() implementation.

The reason for heaving a separate enter() and leave() pair of functions is to help with the possibility that your run() function throws and is not waited on. If the parent thread is working on something else or waiting on a different thread, then you would have no idea that the thread is ending.

Attention
The enter() will always be called, but the run() and leave() functions do not get called if a preceeding call ends in an abnormal manner (i.e. such as emitting an abort() call, a SEGV, etc.) Exceptions are properly handled, however, if the enter() function exits with an exception, then the run() function doesn't get called.

Definition at line 183 of file runner.cpp.

References cppthread::end(), f_thread, get_name(), cppthread::thread::get_thread_tid(), and cppthread::log.

Referenced by cppthread::thread::internal_enter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_name()

std::string const & cppthread::runner::get_name ( ) const

This function returns the name of the runner as specified in the constructor.

Since the name is read-only, it will always match one to one what you passed on.

Returns
The name of this thread runner.

Definition at line 106 of file runner.cpp.

References f_name.

Referenced by enter(), cppthread::thread::init(), cppthread::thread::internal_thread(), and leave().

Here is the caller graph for this function:

◆ get_thread()

thread * cppthread::runner::get_thread ( ) const

Each runner is assigned a thread controller whenever the thread is created (they get attached, in effect.) Once the thread is destroyed, the pointer goes back to nullptr.

Returns
A thread pointer or nullptr.

Definition at line 258 of file runner.cpp.

References f_thread.

◆ gettid()

pid_t cppthread::runner::gettid ( ) const

This function returns the thread identifier of the thread running this runner run() function.

This function can be called from any thread and the correct value will be returned.

Returns
The thread identifier.

Definition at line 274 of file runner.cpp.

References f_thread, and cppthread::thread::get_thread_tid().

Here is the call graph for this function:

◆ is_ready()

bool cppthread::runner::is_ready ( ) const
virtual

By default a thread runner is considered ready. If you override this function, it is possible to tell the thread controller that you are not ready. This means the start() function fails and returns false.

Returns
true by default, can return false to prevent a start() command.

Definition at line 120 of file runner.cpp.

Referenced by cppthread::thread::start().

Here is the caller graph for this function:

◆ leave()

void cppthread::runner::leave ( leave_status_t  status)
virtual

This function is called whenever the run() function is done. It may also be called if the enter() function throws in which case the run() function does not get called but the leave() function still gets called.

This function is useful to know that the run() function returned without you having to instrument your run() function with a try/catch. This is particularly useful to detect that a thread died when not expected. Specifically, if your parent thread is not activelly waiting on your thread demise, the fact that the run() function threw an exception will not be known until later if ever. The leave() function can act in such a way that the parent thread is then aware of the issue and either quits, restarts the thread, or just reports the issue.

The status parameter defines which location the leave() function is called from. It can be called in the following cases:

  • LEAVE_STATUS_NORMAL – the enter() and run() functions worked as expected.
  • LEAVE_STATUS_INITIALIZATION_FAILED – the enter() function failed with an exception; the run() function was never called.
  • LEAVE_STATUS_THREAD_FAILED – the run() function was called and it generated an exception.
  • LEAVE_STATUS_INSTRUMENTATION – a function, other than the enter() or run() functions, generated an error.

The default function logs the fact that the thread is exiting. You often call it at the end of your own leave() implementation.

Parameters
[in]statusThe location from which the leave() function gets called.

Definition at line 231 of file runner.cpp.

References cppthread::end(), f_thread, get_name(), cppthread::thread::get_thread_tid(), and cppthread::log.

Referenced by cppthread::thread::internal_leave().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

cppthread::runner::operator= ( runner const &  rhs)
delete

A runner represents a running thread which is pretty much impossible to copy so we prevent such of the class too.

Parameters
[in]rhsThe right hand side.
Returns
A reference to this object.

◆ run()

cppthread::runner::run ( )
pure virtual

The run() function is the one you have to implement in order to have something to execute when the thread is started.

To exit the thread, simply return from the run() function.

Implemented in cppthread::worker< T >.

Referenced by cppthread::thread::internal_run().

Here is the caller graph for this function:

Friends And Related Symbol Documentation

◆ thread

friend class thread
friend

This definition allows the thread to access the f_thread field in the runner. This allows the thread objects to know whether the runner is currently assigned to a thread or not. One runner cannot be assigned to more than one thread at a time.

Definition at line 96 of file runner.h.

Member Data Documentation

◆ f_mutex

cppthread::runner::f_mutex = mutex()
mutableprotected

Each thread is given its own mutex so it can handle its data safely.

This mutex is expected to mainly be used by the thread and its parent.

If you want to share data and mutexes between multiple threads, you may want to consider using another mutex. For example, the cppthread::fifo is itself derived from the mutex class. So when you use a FIFO between multiple threads, the lock/unlock mechanism is not using the mutex of your thread.

Definition at line 86 of file runner.h.

Referenced by continue_running(), cppthread::worker< T >::is_working(), cppthread::worker< T >::run(), and cppthread::worker< T >::runs().

◆ f_name

cppthread::runner::f_name = std::string()
private

Each thread is given a name. This can help greatly when debugging a threaded environment with a large number of threads. That way you can easily identify which thread did what and work you way to a perfect software.

On some systems it may be possible to give this name to the OS which then can be displayed in tools listing processes and threads.

Definition at line 99 of file runner.h.

Referenced by ~runner(), and get_name().

◆ f_thread

cppthread::runner::f_thread = nullptr
private

When a snap_runner is created, it gets created by a specific parent object. This pointer holds that parent.

The runner uses this pointer to know whether it is still running and to retrieve its identifier that the parent holds.

Definition at line 98 of file runner.h.

Referenced by ~runner(), cppthread::thread::~thread(), continue_running(), enter(), get_thread(), gettid(), cppthread::thread::init(), and leave().


The documentation for this class was generated from the following files:

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.