cppthread 1.1.16
C++ Thread Library
Public Types | Public Member Functions | Protected Attributes | Private Attributes | List of all members
cppthread::worker< T > Class Template Referenceabstract

A runner augmentation allowing for worker threads. More...

Inheritance diagram for cppthread::worker< T >:
Inheritance graph
[legend]
Collaboration diagram for cppthread::worker< T >:
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.
 
typedef T work_load_type
 Type T of the worker.
 

Public Member Functions

 worker (std::string const &name, std::size_t position, typename fifo< T >::pointer_t in, typename fifo< T >::pointer_t out)
 Initialize a worker thread.
 
 worker (worker const &rhs)=delete
 Deleted copy operator.
 
virtual bool continue_running () const
 Whether the thread should continue running.
 
virtual bool do_work ()=0
 Worker Function.
 
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.
 
bool is_working () const
 Check whether this specific worker thread is busy.
 
virtual void leave (leave_status_t status)
 Signal that the run() function has returned.
 
worker< T > & operator= (worker< T > const &rhs)=delete
 Deleted assignment operator.
 
std::size_t position () const
 Get the worker thread position.
 
virtual void run ()
 Implement the worker loop.
 
size_t runs () const
 Number of time this worker got used.
 

Protected Attributes

fifo< T >::pointer_t f_in
 The input fifo.
 
mutex f_mutex = mutex()
 The mutex of this thread.
 
fifo< T >::pointer_t f_out
 The output fifo.
 
f_payload = T()
 The payload this worker is processing.
 

Private Attributes

std::string const f_name = std::string()
 The name of this thread.
 
std::size_t const f_position
 The position of this worker in the pool.
 
std::size_t f_runs = 0
 The number of times this worker ran.
 
threadf_thread = nullptr
 A pointer back to the owner ("parent") of this runner.
 
bool f_working = false
 Whether this worker is currently working (true) or not (false).
 

Detailed Description

template<class T>
class cppthread::worker< T >

This class allows you to create a pool of worker threads. This is useful to add/remove work in a fifo object and have any one worker thread pick up the next load as soon as it becomes available. This is pretty much the fastest way to get work done using threads, however, it really only works if you can easily break down the work by chunk.

One pool of worker threads is expected to share one pair of fifo objects. Also the input and output fifo objects must be of the same type. The output can be set to nullptr if you create all the payloads ahead of time or create new items in the current threads. Both methods work fine.

To use your pool of threads, all you have to do is add data to the input fifo and grab results from the output fifo. Note that the output fifo of one pool of threads can be the input fifo of another pool of threads or even the input fifo in which case further work can be sent to the same pool of workers.

Definition at line 41 of file worker.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.

◆ work_load_type

template<class T >
cppthread::worker< T >::work_load_type

This type can be used to extract the worker's type as defined by T.

Definition at line 45 of file worker.h.

Constructor & Destructor Documentation

◆ worker() [1/2]

template<class T >
cppthread::worker< T >::worker< T > ( std::string const &  name,
std::size_t  position,
typename fifo< T >::pointer_t  in,
typename fifo< T >::pointer_t  out 
)
inline

This function initializes a worker thread. The name should be different for each worker, although there is no test to verify that.

The in and out parameters are pointers to fifo objects used to receive work and return work that was done. The output is optional (you can pass a null pointer). The input can be a class derived from the item_with_predicate if you want to allow dependencies (i.e. prevent a thread to work on a certain item until another thread is done with a certain number of other packets).

Keep in mind that data added and removed from the fifo is being copied. It is suggested that you make use of a shared_ptr<> to an object and not directly an object. This is likely to make the push/pop more effective.

Parameters
[in]nameThe name of this new worker thread.
[in]positionThe worker thread position.
[in]inThe input FIFO.
[in]outThe output FIFO.

Definition at line 47 of file worker.h.

References cppthread::worker< T >::f_in.

◆ worker() [2/2]

template<class T >
cppthread::worker< T >::worker< T > ( worker< T > const &  rhs)
delete

The copy operator is deleted to clearly prevent copying workers. Threads cannot easily be duplicated, especially the PC, stack, local variables...

Parameters
[in]rhsThe right hand side item.

Member Function Documentation

◆ continue_running()

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

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 cppthread::runner::f_mutex, cppthread::runner::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:

◆ do_work()

template<class T >
cppthread::worker< T >::do_work ( )
pure virtual

This function is your worker function which performs work against a pay load automatically retrieved in the run() function.

Your load is available in the f_payload variable member. You are free to modify it. The worker object ignores its content. It retrieved it from the input fifo (f_in) and saves it in the output fifo once done (f_out) assuming your function returns true and there is an output fifo.

Note
The f_out fifo can be set to a null pointer in which case, no forwarding happens.
Returns
true if the work is considered successful and the payload should be forwarded. On false, the payload does not get forwarded to the output fifo.

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

Here is the caller graph for this function:

◆ enter()

void cppthread::runner::enter ( )
virtualinherited

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(), cppthread::runner::f_thread, cppthread::runner::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
inherited

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 cppthread::runner::f_name.

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

Here is the caller graph for this function:

◆ get_thread()

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

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 cppthread::runner::f_thread.

◆ gettid()

pid_t cppthread::runner::gettid ( ) const
inherited

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 cppthread::runner::f_thread, and cppthread::thread::get_thread_tid().

Here is the call graph for this function:

◆ is_ready()

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

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:

◆ is_working()

template<class T >
cppthread::worker< T >::is_working ( ) const
inline

This function let you know whether this specific worker thread picked a pay load and is currently processing it. The processing includes copying the data to the output FIFO. However, there is a small period of time between the time another pay load object is being picked up and the time it gets used that the thread is not marked as working yet. So in other words, this function may be lying at that point.

Returns
Whether the thread is still working.

Definition at line 71 of file worker.h.

References cppthread::runner::f_mutex, and cppthread::worker< T >::f_working.

◆ leave()

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

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(), cppthread::runner::f_thread, cppthread::runner::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=()

template<class T >
cppthread::worker< T >::operator= ( worker< T > const &  rhs)
delete

The assignment operator is deleted to clearly prevent copying of workers. Threads cannot easily be duplicated, especially the PC, stack, local variables...

Parameters
[in]rhsThe right hand side item.
Returns
a reference to this.

◆ position()

template<class T >
cppthread::worker< T >::position ( ) const
inline

Whenever the cppthread_pool class creates a worker thread, it assigns a position to it. The position is not used, but it may help you when you try to debug the system.

Returns
This worker thread position in the cppthread_pool vector.

Definition at line 66 of file worker.h.

References cppthread::worker< T >::f_position.

◆ run()

template<class T >
cppthread::worker< T >::run ( )
inlinevirtual

This function is the overload of the runner::run() function. It takes care of waiting for more data and run your process by calling the do_work() function.

You may reimplement this function if you need to do some initialization or clean up as follow:

virtual void run()
{
// initialize my variable
m_my_var = allocate_object();
// make sure to delete that resource
delete_object(m_my_var);
}
virtual void run()
Implement the worker loop.
Definition worker.h:83

Implements cppthread::runner.

Definition at line 83 of file worker.h.

References cppthread::runner::continue_running(), cppthread::worker< T >::do_work(), cppthread::worker< T >::f_in, cppthread::runner::f_mutex, cppthread::worker< T >::f_out, cppthread::worker< T >::f_payload, cppthread::worker< T >::f_runs, and cppthread::worker< T >::f_working.

Here is the call graph for this function:

◆ runs()

template<class T >
cppthread::worker< T >::runs ( ) const
inline

This function returns the number of time this worker ended up running against a pay load.

The function may return 0 if the worker never ran. If you create a large pool of threads but do not have much work, this is not unlikely to happen.

Returns
Number of times this worker ran your do_work() function.

Definition at line 77 of file worker.h.

References cppthread::runner::f_mutex, and cppthread::worker< T >::f_runs.

Member Data Documentation

◆ f_in

template<class T >
cppthread::worker< T >::f_in
protected

This variable member holds the input fifo. It must be defined since this is the only way a worker thread actually receives work.

Definition at line 137 of file worker.h.

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

◆ f_mutex

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

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 cppthread::runner::continue_running(), cppthread::worker< T >::is_working(), cppthread::worker< T >::run(), and cppthread::worker< T >::runs().

◆ f_name

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

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 cppthread::runner::~runner(), and cppthread::runner::get_name().

◆ f_out

template<class T >
cppthread::worker< T >::f_out
protected

This variable member holds the output fifo pointer.

The pointer can be set to nullptr in which case the payload gets dropped at the time the thread returns from its do_work() function.

Definition at line 138 of file worker.h.

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

◆ f_payload

template<class T >
cppthread::worker< T >::f_payload = T()
protected

This is the payload, an item from the input fifo, which this thread is expected to work on.

Once the thread returns, that payload will be forwarded to the output fifo is there is one.

Definition at line 136 of file worker.h.

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

◆ f_position

template<class T >
cppthread::worker< T >::f_position
private

The pool object creates the workers and assigns a position to each one of them. This can be useful in various situations such as while debugging your software.

Definition at line 141 of file worker.h.

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

◆ f_runs

template<class T >
cppthread::worker< T >::f_runs = 0
private

For statistical purposes, you can use the runs() function which returns the number of time this runner was given the chance to work on a payload.

Definition at line 143 of file worker.h.

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

◆ f_thread

cppthread::runner::f_thread = nullptr
privateinherited

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 cppthread::runner::~runner(), cppthread::thread::~thread(), cppthread::runner::continue_running(), cppthread::runner::enter(), cppthread::runner::get_thread(), cppthread::runner::gettid(), cppthread::thread::init(), and cppthread::runner::leave().

◆ f_working

template<class T >
cppthread::worker< T >::f_working = false
private

The worker sets this flag to true before calling the do_work(). It then sets it back to false on return.

Note
At the moment, the flag remains set to true if an exception occurs. This is on purpose because that state is not expected.

Definition at line 142 of file worker.h.

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


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.