typetui 0.1.0

A terminal-based typing test.
Documentation
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <queue>
#include <functional>
#include <future>

template<typename T>
class ThreadSafeQueue {
    std::queue<T> queue;
    mutable std::mutex mtx;
    std::condition_variable cv;
    bool stop_flag = false;

public:
    void push(T item) {
        {
            std::lock_guard<std::mutex> lock(mtx);
            queue.push(std::move(item));
        }
        cv.notify_one();
    }

    bool pop(T& item) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [this] { return !queue.empty() || stop_flag; });

        if (queue.empty()) return false;

        item = std::move(queue.front());
        queue.pop();
        return true;
    }

    void stop() {
        {
            std::lock_guard<std::mutex> lock(mtx);
            stop_flag = true;
        }
        cv.notify_all();
    }
};

class Counter {
    std::atomic<int> value{0};

public:
    void increment() {
        value.fetch_add(1, std::memory_order_relaxed);
    }

    int get() const {
        return value.load(std::memory_order_relaxed);
    }
};

class ThreadPool {
    std::vector<std::thread> workers;
    ThreadSafeQueue<std::function<void()>> tasks;

public:
    explicit ThreadPool(size_t num_threads) {
        for (size_t i = 0; i < num_threads; ++i) {
            workers.emplace_back([this] {
                std::function<void()> task;
                while (tasks.pop(task)) {
                    task();
                }
            });
        }
    }

    template<typename F>
    void submit(F&& f) {
        tasks.push(std::forward<F>(f));
    }

    ~ThreadPool() {
        tasks.stop();
        for (auto& worker : workers) {
            worker.join();
        }
    }
};

int main() {
    auto future = std::async(std::launch::async, []() -> int {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        return 42;
    });

    std::cout << "Result: " << future.get() << "\n";

    Counter counter;
    std::vector<std::thread> threads;

    for (int i = 0; i < 10; ++i) {
        threads.emplace_back([&counter] {
            for (int j = 0; j < 100; ++j) {
                counter.increment();
            }
        });
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "Counter: " << counter.get() << "\n";

    return 0;
}