|
| rthread () noexcept |
| Default constructor. You can subclass this constructor and/or create parameterized constructors, any of which may throw exceptions (even though this default one doesn't).
|
|
virtual | ~rthread () noexcept |
| Default destructor. Called only after two conditions are met:
|
|
virtual void | _rthread_exceptions (std::exception *e) noexcept |
| Final rthread exception handler. If an uncaught exception is thrown from the run() method in a running rthread, then it will be handled by this method (which is still technically running on the underlying pthread). Override this method to handle known and unknown exceptions gracefully, before the destructor (or reinitiator) runs.
|
|
virtual void | _rthread_reinitialize () noexcept |
| Re-initialize internal variables, refresh resources, etc., before re-running a reuseable rthread. When utilizing the reuseable feature, this method can be thought of as having similar functionality to that of the constructor, except that it is used to do the following to bring internal variables and resources back to the same state that the constructor originally initialized them to, and thus reducing construction overhead (some variables may not need re-initializing, which can also help to further-reduce overhead):
|
|
rthread * | detach () |
| Daemonize this rthread.
|
|
bool | detached () noexcept |
| Find out whether this rthread is daemonized.
|
|
rthread * | join () |
| Join this rthread to the current thread that called this method. (This is how non-daemonized threads are normally terminated.)
|
|
pthread_t | pthread_id () noexcept |
| Find out what the underlying pthread_id is.
|
|
bool | reuseable () noexcept |
| Find out whether this rthread can be re-used.
|
|
rthread * | reuseable (bool flag) noexcept |
| Configure whether this rthread can be re-used.
|
|
virtual void | run ()=0 |
| Thread functionality (subclassing this method is required).
|
|
ulong | run_count () noexcept |
| Find out how many times this rthread was started. This method is only really meaningful for reuseable rthreads.
|
|
bool | running () noexcept |
| Find out whether this rthread is actively running.
|
|
rthread * | start () |
| Commence execution of the run() method as a separate rthread.
|
|
rthread * | start_detached () |
| Commence execution of the run() method as a separate thread in a daemonized state.
|
|
rthread * | stop () noexcept |
| Request the graceful termination of this rthread.
|
|
This rthread thread library provides an easier and sufficiently-complete object-oriented thread interface class for C++ that adds a properly-honoured destructor, and without terminating the entire application when the thread throws an exception (a virtual method for optionally catching and handling all exceptions is also provided).
POSIX threads are the foundation of the rthread class, and the resulting C++ interface will probably seem familiar to those who are familliar with Java.
- Features
- This is meant to be a safe and easy-to-use thread class for C++, which is intended to make thread sub-classing straight-forward in a logical manner for developers. Some of the key features are:
- Customizable constructor that doesn't automatically start the thread
- Better control with the start() method to start a previously constructed rthread
- Abstract run() method (required)
- This method contains the code that will be run in its own thread
- Customizable destructor that occurs only after the thread ends (which is particularly useful for daemon threads {a.k.a., detached threads})
- Customizable exception handler method (just subclass it to use it)
- Most methods are designed to be thread-safe (e.g., status methods)
Some advanced features are planned that exceed what the basic thread functions provide, but are also needed:
- thread groups (separate class), possibly with support for including threads in multiple groups
- thread pool (separate class)
- Background
- I created this class to make it easier to write internet server daemons. I started out using C-style thread functions (because C++ doesn't come with a thread class that can be sub-classed), and even with std::jthreads I ran into a serious problem with the thread's destructor executing while the thread was still running (the code that started it went out of scope) – this is not what I expected because the running thread should really be an additional criteria for thread destruction (this is a serious concern since the premature destruction of a running thread usually results in a segmentation fault or other unpredictable behaviour that has the potential to cause the Operating System to exhibit other strange behaviours or even crash entirely).
After looking for existing solutions (none of which resolved the ineherent problems with threads in C++), I embarked on creating this rthread class, which was highly educational but also wasn't difficult. The end result is a small class that's easy to maintain, eliminates the reliability concerns, and is easy to use primarily because C++ thoroughly supports subclassing.
My background in programming began when I was a young child, teaching myself BASIC and then machine language (when I found BASIC to be too limited) before moving on to other languages like Perl and Java many years later. Eventually I circled around to C (which I chose to learn the hard way by writing some PostgreSQL extensions) and then C++ a few years after that. I have a lot of experience with programming threadded applications on a variety of platforms that support pthreads (including Novell's NetWare), running application code I created that ran hundreds of thousands of threads successfully serving a similar number of users globally without slowdowns or crashes.
- History
- 2022-Oct-22 v1.00 Initial version
- 2024-Oct-23 v1.00 Various minor improvements to the documentation since the previous update
- Version
- 1.00
- Author
- Randolf Richardson
virtual randolf::rthread::~rthread |
( |
| ) |
|
|
inlinevirtualnoexcept |
Default destructor. Called only after two conditions are met:
- this rthread has gone out of scope
- termination of the underlying pthread (this is different from the standard C++ implementation of threads and jthreads, which don't have this criteria)
Exceptions are handled by the _rthread_exceptions() method before this destructor is activated.
You can add your own destructor to safely ensure that files and sockets are closed, and that resources are freed, deallocated, deleted, etc., which is essential to preventing various types of resource leaks if your thread code (in the run() method) exited early due to an unexpected exception (it is the developer's responsibility to ensure resources are managed properly, and this destructor provides a means of handling this reliably).
Logging, re-queuing, semaphore completions, etc., can also be handled in this method because it runs after the termination of the underlying pthread.
- Warning
- Do not throw exceptions from this method. If you're relying on a function or a class that might throw exceptions (intended or otherwise), then you need to take care to at least utilize a final try/catch block for
std::exception
.