LibThreadPool

A lightweight, single-header C++ thread pool library with task prioritization

C++11 Header-Only MIT License Thread-Safe Cross-Platform

Why LibThreadPool?

⚡

Lightweight

Single-header implementation. Just include and use—no builds or installations needed. Perfect for rapid development.

🚀

High Performance

Efficient task management with priority queue. Execute high-priority tasks first while maintaining FIFO order for same-priority tasks.

🔒

Thread-Safe

Built with std::mutex and std::condition_variable for safe concurrent task execution without race conditions.

🌍

Portable

Built with C++11 standard. Works seamlessly on Linux, macOS, Windows, and other platforms supporting C++11.

🎯

Easy to Use

Intuitive API with future/promise support. Get results from asynchronous tasks with minimal boilerplate code.

⚙️

Flexible

Singleton pattern with configurable thread count. Automatically scales to hardware concurrency or use custom thread count.

Installation

Getting started with LibThreadPool is incredibly simple. Since it's a header-only library, you just need to include the header file in your project.

Step 1: Download

Download the threadpool.h file from the repository or SourceForge.

Step 2: Include in Your Project

Copy threadpool.h to your project directory and include it:

#include "threadpool.h"

Step 3: Compile

Compile your project with C++11 support and pthread library:

g++ -std=c++11 your_program.cpp -pthread -o your_program

That's it! You're ready to use LibThreadPool in your project.

Basic Usage

Quick Start

Here's a simple example to get you started:

#include <iostream>
#include "threadpool.h"

int main() {
    // Initialize thread pool with 4 threads
    InitializeThreadPool(4);
    
    // Enqueue a simple task with priority 1
    auto result = GetThreadPool()->enqueue(1, []() {
        std::cout << "Hello from thread pool!" << std::endl;
        return 42;
    });
    
    // Wait for result
    std::cout << "Result: " << result.get() << std::endl;
    
    return 0;
}

Working with Priorities

Tasks with lower priority values execute first:

#include <iostream>
#include <chrono>
#include <thread>
#include "threadpool.h"

void task(int id, int priority) {
    std::cout << "Task " << id 
              << " (priority " << priority << ") executing\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

int main() {
    InitializeThreadPool(2);
    
    // Enqueue tasks with different priorities
    GetThreadPool()->enqueue(5, task, 1, 5);  // Low priority
    GetThreadPool()->enqueue(1, task, 2, 1);  // High priority - executes first
    GetThreadPool()->enqueue(3, task, 3, 3);  // Medium priority
    GetThreadPool()->enqueue(1, task, 4, 1);  // High priority - executes second
    
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 0;
}

Getting Return Values

Use std::future to retrieve results from tasks:

#include <iostream>
#include <vector>
#include "threadpool.h"

int calculate(int x) {
    return x * x;
}

int main() {
    InitializeThreadPool(4);
    
    std::vector<std::future<int>> results;
    
    // Enqueue multiple calculations
    for (int i = 1; i <= 10; ++i) {
        results.push_back(
            GetThreadPool()->enqueue(1, calculate, i)
        );
    }
    
    // Collect results
    for (auto& result : results) {
        std::cout << result.get() << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

Lambda Functions with Captures

#include <iostream>
#include "threadpool.h"

int main() {
    InitializeThreadPool(4);
    
    int multiplier = 5;
    
    auto result = GetThreadPool()->enqueue(1, [multiplier](int x) {
        return x * multiplier;
    }, 10);
    
    std::cout << "Result: " << result.get() << std::endl; // Output: 50
    
    return 0;
}

API Reference

Initialization

Function Description
InitializeThreadPool(n) Initialize the thread pool with n threads. If not called, defaults to std::thread::hardware_concurrency()
GetThreadPool() Returns pointer to the singleton thread pool instance

Core Methods

Method Description Returns
enqueue(priority, func, args...) Add a task to the thread pool with specified priority (lower = higher priority) std::future<ReturnType>

Task Structure

Each task contains:

Thread Safety

All public methods are thread-safe and can be called from multiple threads simultaneously. The library uses:

Advanced Examples

Example 1: Parallel File Processing

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include "threadpool.h"

void processFile(const std::string& filename) {
    std::ifstream file(filename);
    // Process file contents...
    std::cout << "Processed: " << filename << std::endl;
}

int main() {
    InitializeThreadPool(8);
    
    std::vector<std::string> files = {
        "file1.txt", "file2.txt", "file3.txt", "file4.txt"
    };
    
    std::vector<std::future<void>> futures;
    
    for (const auto& file : files) {
        futures.push_back(
            GetThreadPool()->enqueue(1, processFile, file)
        );
    }
    
    // Wait for all files to be processed
    for (auto& future : futures) {
        future.get();
    }
    
    return 0;
}

Example 2: Producer-Consumer Pattern

#include <iostream>
#include <vector>
#include <random>
#include "threadpool.h"

void producer(int id) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 100);
    
    int data = dis(gen);
    std::cout << "Producer " << id << " generated: " << data << std::endl;
}

void consumer(int id, int data) {
    std::cout << "Consumer " << id << " processing: " << data << std::endl;
}

int main() {
    InitializeThreadPool(4);
    
    // High priority for producers
    for (int i = 0; i < 5; ++i) {
        GetThreadPool()->enqueue(1, producer, i);
    }
    
    // Lower priority for consumers
    for (int i = 0; i < 5; ++i) {
        GetThreadPool()->enqueue(2, consumer, i, i * 10);
    }
    
    std::this_thread::sleep_for(std::chrono::seconds(2));
    return 0;
}

Example 3: Image Processing Pipeline

#include <iostream>
#include <vector>
#include "threadpool.h"

struct Image {
    std::string filename;
    // Image data...
};

Image loadImage(const std::string& path) {
    std::cout << "Loading: " << path << std::endl;
    return Image{path};
}

Image applyFilter(const Image& img) {
    std::cout << "Filtering: " << img.filename << std::endl;
    return img;
}

void saveImage(const Image& img, const std::string& output) {
    std::cout << "Saving to: " << output << std::endl;
}

int main() {
    InitializeThreadPool(4);
    
    std::vector<std::string> images = {
        "img1.jpg", "img2.jpg", "img3.jpg"
    };
    
    for (const auto& imgPath : images) {
        auto loadFuture = GetThreadPool()->enqueue(1, loadImage, imgPath);
        auto filterFuture = GetThreadPool()->enqueue(2, applyFilter, loadFuture.get());
        GetThreadPool()->enqueue(3, saveImage, filterFuture.get(), "output_" + imgPath);
    }
    
    std::this_thread::sleep_for(std::chrono::seconds(3));
    return 0;
}

Resources & References

Learn More

Related Topics

License

LibThreadPool is released under the MIT License. You are free to use, modify, and distribute this library in your projects, whether they are open source or commercial.

Contributing

Found a bug or have a feature request? Feel free to open an issue or submit a pull request on the project repository. Contributions are always welcome!