|
cppthread 1.1.16
C++ Thread Library
|
A thread object that ensures proper usage of system threads. More...

Public Types | |
| typedef std::shared_ptr< thread > | pointer_t |
| The shared pointer for a thread object. | |
| typedef std::vector< pointer_t > | vector_t |
| A vector of threads. | |
Public Member Functions | |
| thread (std::string const &name, runner *runner) | |
| Initialize the thread object. | |
| thread (std::string const &name, std::shared_ptr< runner > runner) | |
| Initialize the thread with a shared pointer to the runner. | |
| thread (thread const &rhs)=delete | |
| The copy operator is deleted. | |
| ~thread () | |
| Delete a thread object. | |
| std::exception_ptr | get_exception () const |
| Get the exception pointer. | |
| bool | get_log_all_exceptions () const |
| Retrieve whether all exceptions get logged or not. | |
| std::string const & | get_name () const |
| Retrieve the name of this process object. | |
| runner * | get_runner () const |
| Get a pointer to this thread runner. | |
| mutex & | get_thread_mutex () const |
| Retrieve a reference to the thread mutex. | |
| pid_t | get_thread_tid () const |
| Retrieve the thread identifier of this thread. | |
| bool | is_running () const |
| Check whether the thread is considered to be running. | |
| bool | is_stopping () const |
| Check whether the thread was asked to stop. | |
| bool | kill (int sig) |
| Send a signal to this thread. | |
| void | mask_all_signals () |
| Block all signals for this thread. | |
| void | mask_signals (libexcept::sig_list_t list) |
| Masks signals from this thread. | |
| thread & | operator= (thread const &rhs)=delete |
| The assignment operator is deleted. | |
| void | set_log_all_exceptions (bool log_all_exceptions) |
| Whether to log exceptions caught in the thread. | |
| bool | start () |
| Attempt to start the thread. | |
| void | stop (std::function< void(thread *)> callback=nullptr) |
| Stop the thread. | |
| void | unmask_signals (libexcept::sig_list_t list) |
| Unmask signals for this thread. | |
Private Member Functions | |
| void | init () |
| This private function initializes the thread. | |
| bool | internal_enter () |
| Enter the thread runner. | |
| void | internal_leave (leave_status_t status) |
| Function called when leaving the thread runner. | |
| bool | internal_run () |
| Execute the run() function. | |
| void | internal_thread () |
| Run the thread process. | |
Private Attributes | |
| std::exception_ptr | f_exception = std::exception_ptr() |
| An exception pointer. | |
| bool | f_log_all_exceptions = true |
| Whether the runner exceptions should be logged or not. | |
| mutex | f_mutex = mutex() |
| The thread mutex to guard various functions. | |
| std::string const | f_name = std::string() |
| The name of this thread. | |
| runner * | f_runner = nullptr |
| The actual thread object. | |
| bool | f_running = false |
| The thread is running. | |
| bool | f_started = false |
| The thread is started. | |
| bool | f_stopping = false |
| The thread is currently in the stopping process. | |
| pthread_attr_t | f_thread_attr = pthread_attr_t() |
| This thread attributes. | |
| pthread_t | f_thread_id = THREAD_UNDEFINED |
| This thread identifier. | |
| pid_t | f_tid = PID_UNDEFINED |
| This thread identifier. | |
Friends | |
| void * | func_internal_start (void *system_thread) |
| Start the actual thread. | |
This class is used to handle threads. It should NEVER be used, however, there are some very specific cases where a thread is necessary to make sure that main process doesn't get stuck. For example, the process environment using pipes requires threads to read and write pipes because otherwise the processes could lock up.
This type is used to hold a smart pointer to a thread.
This smart pointer is safe. It can be used to hold a thread object and when it goes out of scope, it properly ends the corresponding thread runner (the runner) and returns.
Be cautious because the smart pointer of a runner is not actually safe to delete without first stopping the thread. Make sure to manage all your threads in with two objects, making sure that the thread goes out of scope first so it can stop your thread before your thread object gets destroyed.
| cppthread::thread::thread | ( | std::string const & | name, |
| runner * | runner | ||
| ) |
This function saves the name of the thread. The name is generally a static string and it is used to distinguish between threads when managing several at once. The function makes a copy of the name.
The runner pointer is an object which has a run() function that will be called from another thread. That object becomes the "child" of this thread controller. However, if it is already assigned a thread controller, then the initialization of the thread fails. You may test whether a runner is already assigned a thread controller by calling its get_thread() function and see that it is not nullptr.
The pointer to the runner object cannot be nullptr.
| [in] | name | The name of the process. |
| [in] | runner | The runner (the actual thread) to handle. |
Definition at line 89 of file thread.cpp.
References init().

| cppthread::thread::thread | ( | std::string const & | name, |
| std::shared_ptr< runner > | runner | ||
| ) |
At times you have a shared pointer to the runner, in which case you can directly use that pointer. This function otherwise works exactly like the other accepting a bare pointer. In other words, the thread does not keep a shared pointer of your runner. It is expected that you do not delete your runner before the thread is done with it.
| [in] | name | The name of the process. |
| [in] | runner | The runner (the actual thread) to handle. |
Definition at line 108 of file thread.cpp.
References init().

|
delete |
The thread object holds a pointer to a runner which is an OS thread. These would be really difficult to copy. Instead we prevent the operation altogether.
| [in] | rhs | The right hand side. |
| cppthread::thread::~thread | ( | ) |
The destructor of a Snap! C++ thread object ensures that the thread stops running before actually deleting the runner object.
Then it destroys the thread attributes and returns.
The destructor also removes the thread from the runner so the runner can be assigned to another thread controller and run again.
Definition at line 175 of file thread.cpp.
References cppthread::end(), f_runner, cppthread::runner::f_thread, f_thread_attr, cppthread::log, and stop().

| std::exception_ptr cppthread::thread::get_exception | ( | ) | const |
When the thread runner raises an exception, it gets saved in the thread object. That exception can be retrieved using this get_exception() function.
If no exception occurred, then this pointer will be the nullptr. If an exception did occur, then it will be a pointer to that exception. It can be rethrown inside a try/catch in order to handle it.
Definition at line 836 of file thread.cpp.
References f_exception, and f_mutex.
| bool cppthread::thread::get_log_all_exceptions | ( | ) | const |
This function returns true if all exceptions are to be logged. By default this flag is set to true. You can change it with the set_log_all_exceptions() function.
Internally, the flag is used to know whether we should log exceptions. It is very useful to do so if you do not join your thread on a constant basis (i.e. in a service where a thread runs as long as the service itself–you probably will want to know when the thread runs in a problem).
This also means you do not have to log the exception yourself unless you need some special handling to indicate all the possible messages and parameters found in the exception object. However, the logging doesn't prevent the system from re-throwing the exception once the thread was joined. In other words, whether you log the exception or not, you most certainly want to catch it or your process will be terminated.
Definition at line 803 of file thread.cpp.
References f_log_all_exceptions.
| std::string const & cppthread::thread::get_name | ( | ) | const |
This process object is given a name on creation. In most cases this is a static name that is used to determine which process is which.
Definition at line 209 of file thread.cpp.
References f_name.
| runner * cppthread::thread::get_runner | ( | ) | const |
This function returns the pointer to the thread runner. There are cases where it is quite handy to be able to use this function rather than having to hold on the information in your own way.
You will probably have to dynamic_cast<>() the result to your own object type.
Definition at line 231 of file thread.cpp.
References f_runner.
| mutex & cppthread::thread::get_thread_mutex | ( | ) | const |
This function returns a reference to this thread mutex. Note that the runner has its own mutex as well.
Definition at line 740 of file thread.cpp.
References f_mutex.
| pid_t cppthread::thread::get_thread_tid | ( | ) | const |
Under Linux, threads are tasks like any others. Each task is given a pid_t value. This function returns that pid_t for this thread.
When the thread is not running this function returns PID_UNDEFINED. Note, however, that the value is set a little after the thread started and cleared a little before the thread exits. This is not a good way to know whether the thread is running. Use the is_running() function instead.
Definition at line 726 of file thread.cpp.
References f_mutex, and f_tid.
Referenced by cppthread::runner::enter(), cppthread::runner::gettid(), and cppthread::runner::leave().

|
private |
We can create the thread with a bare pointer or a shared pointer. This function does the remaining of the initialization.
Definition at line 121 of file thread.cpp.
References cppthread::end(), f_runner, cppthread::runner::f_thread, f_thread_attr, cppthread::runner::get_name(), and cppthread::log.
Referenced by thread(), and thread().


|
private |
This function signals that the thread runner is about to be entered. This is often used as an initialization function.
If the runner::enter() function raises an std::exception, then the function saves that exception for the thread owner, emits a log, and returns false.
Definition at line 434 of file thread.cpp.
References cppthread::end(), cppthread::runner::enter(), f_exception, f_log_all_exceptions, f_runner, and cppthread::log.
Referenced by internal_thread().


|
private |
Whenever the thread runner leaves, we want to send a signal to the runner owner through the runner::leave() function. This is the thread function which makes sure that the runner::leave() function get called.
The function is called with a status which tells us what failed (i.e. the reason for the call).
The function is std::exception safe. Unknown exceptions are ignored here since they will be caught by the internal_thread() function.
std::exceptions are reported and either ignored (another exception occurred earlier) or reported back to the thread owner after the owner joins with the thread.
| [in] | status | The status when the internal_leave() function gets called. |
Definition at line 528 of file thread.cpp.
References cppthread::end(), f_exception, f_log_all_exceptions, f_runner, cppthread::runner::leave(), and cppthread::log.
Referenced by internal_thread().


|
private |
This function specifically calls the run() function in an exception safe manner.
If no exception occurs, the function returns true meaning that everything worked as expected.
When an std::exception occurs, the function returns false after saving the exception so it can be reported to this thread owner. (i.e. it gets re-thrown whenever the thread owner joins with the thread).
The std::exception can be logged by calling the set_log_all_exceptions() function with true, which is the default (i.e. don't call it with false if you want to get the logs).
Other exceptions are ignored (they will be caught by the internal_thread() function).
Definition at line 483 of file thread.cpp.
References cppthread::end(), f_exception, f_log_all_exceptions, f_runner, cppthread::log, and cppthread::runner::run().
Referenced by internal_thread().


|
private |
This function is called by the func_internal_start() so we run from within the thread class. (i.e. the func_internal_start() function itself is static.)
The function marks the thread as started which allows the parent start() function to return.
Definition at line 318 of file thread.cpp.
References cppthread::end(), f_exception, f_log_all_exceptions, f_mutex, f_runner, f_running, f_started, f_tid, cppthread::runner::get_name(), cppthread::gettid(), internal_enter(), internal_leave(), internal_run(), cppthread::log, cppthread::PID_UNDEFINED, cppthread::set_current_thread_name(), and cppthread::mutex::signal().

| bool cppthread::thread::is_running | ( | ) | const |
This flag is used to know whether the thread is running.
Definition at line 253 of file thread.cpp.
| bool cppthread::thread::is_stopping | ( | ) | const |
The thread is using three status flags. One of them is f_stopping which is set to false (which is also the default status) when start() is called and to true when stop() is called. This function is used to read that flag status from the continue_running() function.
Definition at line 269 of file thread.cpp.
References f_mutex, and f_stopping.
Referenced by cppthread::runner::continue_running().

| bool cppthread::thread::kill | ( | int | sig | ) |
This function sends a signal to this specific thread.
You have to be particularly careful with Unix signal and threads as they do not always work as expected. This is yet particularly useful if you want to send a signal such as SIGUSR1 and SIGUSR2 to a thread so it reacts one way or another (i.e. you are using poll() over a socket and need to be stopped without using a possibly long time out, you can use the signalfd() function to transform SIGUSR1 into a poll-able signal.)
| [in] | sig | The signal to send to this thread. |
Definition at line 862 of file thread.cpp.
References f_mutex, f_running, and f_thread_id.
| void cppthread::thread::mask_all_signals | ( | ) |
After this call, all Unix signals will be masked (except for the few that can never be masked such as SIGKILL).
Note that by default a thread always starts with all its signals blocked. In most cases, you want to leave them that way. This function is useful only if you call the unmask_signals() to unblock some signals for some time.
Definition at line 927 of file thread.cpp.
| void cppthread::thread::mask_signals | ( | libexcept::sig_list_t | list | ) |
The thread has a signal mask that can be used to prevent delivery of signals to that thread. In our event dispatcher environment, all threads should have their signals masked because in most cases the threads will just die on a signal. This is because the event dispatcher system uses the fdsignal() and thus does not make use of handler. The default handler for most signal will terminate the whole process.
| [in] | list | The list of signals to block. |
Definition at line 892 of file thread.cpp.
|
delete |
The thread object holds a pointer to a runner which is an OS thread. These would be really difficult to assign. Instead we prevent the operation altogether.
| [in] | rhs | The right hand side. |
| void cppthread::thread::set_log_all_exceptions | ( | bool | log_all_exceptions | ) |
We catch exceptions that happen in your threads. By default, we log them with the basic cppthread log mechanism. If you do not want to have this intermediate logging kick in, you can set this flag to false.
This flag is defaulted to true because in many cases you are not joining a thread when the exception occurs. That means your code would never see the exception. Instead, you'd have a dangling process as it is likely to expect things are happening in the thread and if not, it gets stuck. At least, in this way, by default you get a message in your logs.
Note that in case of the leave() callback, it may also generate an exception when one of enter() or run() may already have generated an exception. In that case, the log is always generated since otherwise you would lose that information.
| [in] | log_all_exceptions | Whether to log (true) all exceptions or not (false). |
Definition at line 775 of file thread.cpp.
References f_log_all_exceptions.
| bool cppthread::thread::start | ( | ) |
This function is used to start running the thread code. If the thread is already running, then the function returns false.
The function makes use of a condition to wait until the thread is indeed started. The function will not return until the thread is started or something failed.
Note that by default all signals are blocked for all our threads. This is much safer because otherwise the default signal handler kicks in and is likely to terminate the whole process. If you want a thread to have some signals unblocked, call the unmask_signals() function as required.
Definition at line 575 of file thread.cpp.
References cppthread::end(), f_exception, f_mutex, f_runner, f_running, f_started, f_stopping, f_thread_attr, f_thread_id, func_internal_start, cppthread::gettid(), cppthread::runner::is_ready(), cppthread::log, and cppthread::mutex::wait().
Referenced by cppthread::life::life().


| void cppthread::thread::stop | ( | std::function< void(thread *)> | callback = nullptr | ) |
This function requests the thread to stop. Note that the function does not actually forcibly stop the thread. It only turns on a flag (namely it makes the is_stopping() function return true) meaning that the thread should stop as soon as possible. This gives the thread the time necessary to do all necessary cleanup before quitting.
The stop function blocks until the thread is done.
| [in] | callback | A function to call after the thread is marked as stopping but before calling join. Useful to send a signal to the child if you could not have done so earlier. |
Definition at line 656 of file thread.cpp.
References f_exception, f_mutex, f_running, f_started, f_stopping, and f_thread_id.
Referenced by cppthread::life::~life(), and ~thread().

| void cppthread::thread::unmask_signals | ( | libexcept::sig_list_t | list | ) |
After this call, all the signals defined in list will be unmasked. This means those signals may be sent to this thread instead of the main application. In most cases, unless you properly define a signal handler, the signals will terminate the whole process.
| [in] | list | The list of signals to unblock. |
Definition at line 947 of file thread.cpp.
|
friend |
This function is called when starting the thread. This is a static function since pthread can only accept such a function pointer.
The function then calls the internal_thread().
| [in] | system_thread | The thread pointer. |
Definition at line 293 of file thread.cpp.
Referenced by start().
|
private |
The exception pointer to the exception that was raised in the runner. By default this pointer is null.
This pointer is reset back to a null pointer each time the start() is called.
This exception must be caught by your function when calling the stop() function. If you don't catch these, then it will stop your process.
Definition at line 112 of file thread.h.
Referenced by get_exception(), internal_enter(), internal_leave(), internal_run(), internal_thread(), start(), and stop().
|
private |
Whenever an exception occurs in a runner, the exception pointer is saved in the runner so it can be re-thrown after we join with that thread.
The main problem here is that certain threads are not joined until we are done with an application. So the exception lingers and there is absolutely no trace of it, especially if you hit Ctlr-C to exit your software, the exception will 100% be lost.
Instead, we have this flag to determine whether the exception should be logged at the time it gets caught instead of just saving it in the pointer. By default the flag is set to true which means we will log the exception immediately. This makes it easy to not forget.
If you use threads to run a quick process and then return/join (i.e. stop()), then setting this flag to false is okay.
Definition at line 108 of file thread.h.
Referenced by get_log_all_exceptions(), internal_enter(), internal_leave(), internal_run(), internal_thread(), and set_log_all_exceptions().
|
mutableprivate |
The mutex is used whenever a variable that may be accessed by different threads is used. Especially, it makes sure that the variables do not get changed too early or too late (i.e. avoid race conditions).
Also the mutex is used to send signals. For example, the thread waits on the runner to start. Once the runner is started, it signals the main thread which can then wake up and return as everything is now well defined.
Definition at line 104 of file thread.h.
Referenced by get_exception(), get_thread_mutex(), get_thread_tid(), internal_thread(), is_running(), is_stopping(), kill(), start(), and stop().
|
private |
For debug purposes, you can give each one of your threads a different name. It gets saved in this string.
Definition at line 102 of file thread.h.
Referenced by get_name().
|
private |
The runner is the object which holds the system thread and runs the commands. We have a separate object because that way we can make sure the runner destructor isn't called while the thread is still running. If that were to happen, then all the virtual functions would be invalid at that point and the system could crash.
So the thread object holds a runner allowing the thread to be destroyed first, which calls the stop() function before the runner gets destroyed.
Definition at line 103 of file thread.h.
Referenced by ~thread(), get_runner(), init(), internal_enter(), internal_leave(), internal_run(), internal_thread(), and start().
|
private |
When the thread is running, this flag is set to true. The start() function sets this flag to true before starting the thread and the internal_run() function sets the flag back to false right before the thread exits.
In other words, the flag is true early and false early. It's not a way to know whether the actual system thread is running or not.
Definition at line 105 of file thread.h.
Referenced by internal_thread(), is_running(), kill(), start(), and stop().
|
private |
|
private |
When the stop() function is called, the flag is set to true until after the caller joined with the thread.
The is_stopping() function returns the current value of that field.
Definition at line 107 of file thread.h.
Referenced by is_stopping(), start(), and stop().
|
private |
When we create a thread we create attributes to assign to the thread on creation. These are the attributes.
These are created once at the time the thread object is created and released when the object is destroyed. The same attributes are reused to re-start the thread over and over again (i.e. start() / stop() sequences).
|
private |
|
private |
Each thread is assigned a unique identifier by the OS.
Definition at line 109 of file thread.h.
Referenced by get_thread_tid(), and internal_thread().
This document is part of the Snap! Websites Project.
Copyright by Made to Order Software Corp.