thrPool Thread Pool Class
Overview
Priority Ordering
Memory Ownership
Thread Safety
Example Programs
Functions
Overview
The thrPool class is used to group threads of one or more processes together. A thread pool is a doubly linked list of thrPoolNode nodes. Each thrPoolNode holds a pointer to a gxThread_t object plus pointers to the previous and next nodes.
The thrPool class only stores and orders thread pointers. It does not start, join, or cancel threads. Those jobs are done by the gxThread pool functions: ConstructThreadPool(), CreateThreadPool(), ConstructThread(), CreateThread(), JoinThread(), RebuildThreadPool(), and DestroyThreadPool(). The gxThread functions that take a thrPool pointer add each new thread with AddThread(), so the thread priority sets its place in the pool.
Copying and assignment are not allowed for either class.
Include file: thrpool.h. Source file: thrpool.cpp.
Priority Ordering
AddThread() places each thread according to its gxThreadPriority value. Higher priorities go toward the head of the pool.
gxTHREAD_PRIORITY_LOW - Added to the back of the pool.
gxTHREAD_PRIORITY_NORMAL - Added after the last node that is not low priority, searching from the tail. If every node is low priority, it is added to the front.
gxTHREAD_PRIORITY_HIGH - Added after the last high priority node, searching from the tail. If there is no high priority node, it is added to the front. High priority threads keep the order they were added. NOTE: 10/14/2026: Fixed. The search used to start at the head and insert after the first high priority node, so high priority threads were out of order once there were more than two of them.
Any other priority value, such as gxTHREAD_PRIORITY_INVALID, is added to the back of the pool.
Memory Ownership
The pool owns its nodes. The thread objects are handled in two different ways:
The remove functions (RemoveHead(), RemoveTail(), RemoveNode(), and RemoveThread()) delete the node only. They return the gxThread_t pointer so the application can destroy the thread properly, for example with gxThread::DestroyThread().
ClearPool() and the thrPool destructor destroy every gxThread_t still in the pool. As of 10/24/2026 (version 6.0) a running, suspended or waiting joinable thread is canceled and, under POSIX, waited for before it is deleted. Before version 6.0 every thread was deleted with a plain delete, even while it was still running. Detached threads cannot be canceled and are deleted without being stopped, so a pool must not be cleared while its detached threads are running. A canceled thread runs its gxThread::ThreadCleanupHandler(), so the gxThread object that created the threads must still exist when the pool is cleared. gxThread::DestroyThreadPool() does the same and then deletes the pool. MakeEmpty() deletes nothing and leaks any nodes still in the pool.
Thread Safety
The thrPool class does no locking. If more than one thread adds, removes, or walks the pool at the same time, the application must protect the pool with its own mutex.
Example Programs
examples_threads/thread_pool - creates, joins, rebuilds, and destroys thread pools with the gxThread pool functions.
examples_threads/priority - adds threads with different priorities to a pool with AddThread().
examples_socket/multi_threaded_server, examples_socket/ssl_server, and examples_socket/http_server - use a thrPool to hold client request threads and manage it with the gxThread pool functions.
Functions
thrPool::AddAfter()
thrPool::AddBefore()
thrPool::AddThread()
thrPool::AddToBack()
thrPool::AddToFront()
thrPool::AllocNode()
thrPool::ClearPool()
thrPool::DetachNode()
thrPool::FindThread()
thrPool::FreeNode()
thrPool::GetHead()
thrPool::GetHead() const
thrPool::GetTail()
thrPool::GetTail() const
thrPool::InsertAfter()
thrPool::InsertAtHead()
thrPool::InsertAtTail()
thrPool::InsertBefore()
thrPool::IsEmpty()
thrPool::IsEmpty() const
thrPool::MakeEmpty()
thrPool::MoveAfter()
thrPool::MoveBefore()
thrPool::MoveToBack()
thrPool::MoveToFront()
thrPool::RemoveHead()
thrPool::RemoveNode()
thrPool::RemoveTail()
thrPool::RemoveThread()
thrPool::SetHead()
thrPool::SetHead(const thrPoolNode *h)
thrPool::SetTail()
thrPool::SetTail(const thrPoolNode *t)
thrPoolNode::GetNext()
thrPoolNode::GetPrev()
thrPoolNode::GetThreadPtr()
thrPoolNode::GetThreadPtr() const
thrPoolNode::SetNext()
thrPoolNode::SetNext(const thrPoolNode *n)
thrPoolNode::SetPrev()
thrPoolNode::SetPrev(const thrPoolNode *p)
thrPoolNode::SetThreadPtr()
thrPoolNode::SetThreadPtr(const gxThread_t *t)
thrPoolNode::thrPoolNode()
thrPoolNode::thrPoolNode(gxThread_t *t)
thrPoolNode::thrPoolNode(const thrPoolNode &ob)
thrPoolNode::operator=()
thrPoolNode::~thrPoolNode()
thrPool::thrPool()
thrPool::thrPool(const thrPool &ob)
thrPool::operator=()
thrPool::~thrPool()
thrPoolNode *thrPool::AddAfter(thrPoolNode *pos, gxThread_t *t)Public member function used to add the thread "t" after the node "pos", ignoring the thread priority. The "pos" node must be in this pool. If the pool is empty, "pos" is ignored. Returns a pointer to the new node, or a null value if the node could not be allocated.
thrPoolNode *thrPool::AddBefore(thrPoolNode *pos, gxThread_t *t)Public member function used to add the thread "t" before the node "pos", ignoring the thread priority. The "pos" node must be in this pool. If the pool is empty, "pos" is ignored. Returns a pointer to the new node, or a null value if the node could not be allocated.
thrPoolNode *thrPool::AddThread(gxThread_t *thread)Public member function used to add a thread to the pool in priority order. See Priority Ordering. Returns a pointer to the new node. Returns a null value if "thread" is null or the node could not be allocated. NOTE: Every node already in the pool must hold a valid thread pointer, because this function reads each thread's priority.
thrPoolNode *thrPool::AddToBack(gxThread_t *t)Public member function used to add the thread "t" to the back of the pool, ignoring the thread priority. Returns a pointer to the new node, or a null value if the node could not be allocated.
thrPoolNode *thrPool::AddToFront(gxThread_t *t)Public member function used to add the thread "t" to the front of the pool, ignoring the thread priority. Returns a pointer to the new node, or a null value if the node could not be allocated.
thrPoolNode *thrPool::AllocNode(gxThread_t *t)Private member function used by the add functions to allocate a new node that holds the thread pointer "t".
void thrPool::ClearPool()Public member function used to empty the pool. Every node is removed and every gxThread_t is destroyed. Running, suspended and waiting joinable threads are canceled and, under POSIX, waited for before they are deleted. The destructor calls this function. NOTE: 10/24/2026: Fixed in version 6.0. The threads used to be deleted with a plain delete without checking their state, so a thread that was still running used freed memory. Under POSIX a canceled thread stops at its next cancellation point, so a thread that never reaches one keeps this function waiting. See Memory Ownership.
void thrPool::DetachNode(thrPoolNode *n)Public member function used to unlink the node "n" from the pool without deleting it or its thread. Nothing happens if the pool is empty or "n" is null. The next and prev pointers of "n" are set to null. NOTE: "n" must be a node in this pool. 10/14/2026: Fixed two problems. If the pool held only one node, it was emptied no matter which node was passed in; now nothing happens unless "n" is that node. The links of the detached node used to keep pointing into the pool.
thrPoolNode *thrPool::FindThread(gxThread_t *t, thrPoolNode *ptr = 0)Public member function used to find the node that holds the thread "t". The search starts at "ptr", or at the head of the pool if "ptr" is null, and moves toward the tail. Threads are matched by pointer. Returns a pointer to the node, or a null value if the thread was not found.
gxThread_t *thrPool::FreeNode(thrPoolNode *n)Private member function used by the remove functions to delete a detached node. The thread is not deleted. Returns the node's thread pointer, or a null value if "n" is null.
thrPoolNode *thrPool::GetHead()Public member function that returns a pointer to the first node in the pool, or a null value if the pool is empty.
thrPoolNode *thrPool::GetHead() constConst version of GetHead(). Returns a non-const pointer to the first node in the pool, or a null value if the pool is empty.
thrPoolNode *thrPool::GetTail()Public member function that returns a pointer to the last node in the pool, or a null value if the pool is empty.
thrPoolNode *thrPool::GetTail() constConst version of GetTail(). Returns a non-const pointer to the last node in the pool, or a null value if the pool is empty.
void thrPool::InsertAfter(thrPoolNode *pos, thrPoolNode *n)Public member function used to link a new or detached node "n" after the node "pos". If the pool is empty, "pos" is ignored and "n" becomes the only node with null next and prev pointers. Otherwise "pos" must be a non-null node in this pool. NOTE: 10/14/2026: Fixed. A node inserted into an empty pool used to keep its old next and prev pointers.
void thrPool::InsertAtHead(thrPoolNode *n)Public member function used to link a new or detached node "n" at the head of the pool.
void thrPool::InsertAtTail(thrPoolNode *n)Public member function used to link a new or detached node "n" at the tail of the pool.
void thrPool::InsertBefore(thrPoolNode *pos, thrPoolNode *n)Public member function used to link a new or detached node "n" before the node "pos". If the pool is empty, "pos" is ignored and "n" becomes the only node with null next and prev pointers. Otherwise "pos" must be a non-null node in this pool. NOTE: 10/14/2026: Fixed. A node inserted into an empty pool used to keep its old next and prev pointers.
int thrPool::IsEmpty()Public member function that returns true if the pool has no nodes.
int thrPool::IsEmpty() constConst version of IsEmpty(). Returns true if the pool has no nodes.
void thrPool::MakeEmpty()Public member function used to set the head and tail pointers to null. No nodes or threads are deleted. Call it only after all the nodes have been removed.
void thrPool::MoveAfter(thrPoolNode *pos, thrPoolNode *n)Public member function used to move the existing node "n" so it follows the node "pos". Both nodes must be in this pool. Nothing happens if "pos" and "n" are the same node. NOTE: 10/14/2026: Fixed. Moving a node next to itself used to corrupt the links.
void thrPool::MoveBefore(thrPoolNode *pos, thrPoolNode *n)Public member function used to move the existing node "n" so it comes before the node "pos". Both nodes must be in this pool. Nothing happens if "pos" and "n" are the same node. NOTE: 10/14/2026: Fixed. Moving a node next to itself used to corrupt the links.
void thrPool::MoveToBack(thrPoolNode *n)Public member function used to move the node "n" to the back of the pool. Nothing happens if "n" is already the tail.
void thrPool::MoveToFront(thrPoolNode *n)Public member function used to move the node "n" to the front of the pool. Nothing happens if "n" is already the head.
gxThread_t *thrPool::RemoveHead()Public member function used to remove the first node in the pool. The node is deleted but the thread is not. Returns the thread pointer for the application to destroy, or a null value if the pool is empty.
gxThread_t *thrPool::RemoveNode(thrPoolNode *n)Public member function used to unlink and delete the node "n". The thread is not deleted. Returns the thread pointer for the application to destroy, or a null value if "n" is null. NOTE: "n" must be a node in this pool, or a node that was detached with DetachNode(). Unlike RemoveHead(), this function does not check for an empty pool, and a detached node is deleted too, which is how a detached node is freed.
gxThread_t *thrPool::RemoveTail()Public member function used to remove the last node in the pool. The node is deleted but the thread is not. Returns the thread pointer for the application to destroy, or a null value if the pool is empty.
gxThread_t *thrPool::RemoveThread(gxThread_t *t)Public member function used to find the thread "t" with FindThread() and remove its node. The thread is not deleted, so it can be destroyed properly if it is still running, suspended, or waiting. Returns the thread pointer, or a null value if the thread was not found in the pool.
void thrPool::SetHead(thrPoolNode *h)Public member function used to set the head pointer directly. No links are updated. Use it with care.
void thrPool::SetHead(const thrPoolNode *h)Const pointer version of SetHead(). The const qualifier is cast away.
void thrPool::SetTail(thrPoolNode *t)Public member function used to set the tail pointer directly. No links are updated. Use it with care.
void thrPool::SetTail(const thrPoolNode *t)Const pointer version of SetTail(). The const qualifier is cast away.
thrPoolNode *thrPoolNode::GetNext()Public member function that returns a pointer to the next node, or a null value if this is the last node.
thrPoolNode *thrPoolNode::GetPrev()Public member function that returns a pointer to the previous node, or a null value if this is the first node.
gxThread_t *thrPoolNode::GetThreadPtr()Public member function that returns the thread pointer held by this node.
gxThread_t *thrPoolNode::GetThreadPtr() constConst version of GetThreadPtr(). Returns the thread pointer held by this node.
void thrPoolNode::SetNext(thrPoolNode *n)Public member function used to set the next node pointer. The pool's head and tail are not updated.
void thrPoolNode::SetNext(const thrPoolNode *n)Const pointer version of SetNext(). The const qualifier is cast away.
void thrPoolNode::SetPrev(thrPoolNode *p)Public member function used to set the previous node pointer. The pool's head and tail are not updated.
void thrPoolNode::SetPrev(const thrPoolNode *p)Const pointer version of SetPrev(). The const qualifier is cast away.
void thrPoolNode::SetThreadPtr(gxThread_t *t)Public member function used to set the thread pointer held by this node. The old thread is not deleted.
void thrPoolNode::SetThreadPtr(const gxThread_t *t)Const pointer version of SetThreadPtr(). The const qualifier is cast away.
thrPoolNode::thrPoolNode()Default node constructor. Sets the thread, next, and prev pointers to null.
thrPoolNode::thrPoolNode(gxThread_t *t)Node constructor that stores the thread pointer "t" and sets the next and prev pointers to null.
thrPoolNode::thrPoolNode(const thrPoolNode &ob)Private copy constructor used to disallow copying.
void thrPoolNode::operator=(const thrPoolNode &ob)Private assignment operator used to disallow assignment.
thrPoolNode::~thrPoolNode()Node destructor. It does nothing. It does not delete the thread.
thrPool::thrPool()Default pool constructor. Creates an empty pool.
thrPool::thrPool(const thrPool &ob)Private copy constructor used to disallow copying.
void thrPool::operator=(const thrPool &ob)Private assignment operator used to disallow assignment.
thrPool::~thrPool()Pool destructor. Calls ClearPool(), which deletes every node and destroys every gxThread_t still in the pool, stopping running joinable threads first. The destructor is not virtual.