SchedulerC++

#include <iostream>
#include <memory>
#include <chrono>
#include <thread>
#include <condition_variable>

using Job = void (*)();

using Error = void (*)(const std::exception&);

class Scheduler {
public:
    Scheduler(size_t size, Error error);

    Scheduler(size_t size, nullptr_t) = delete;

    Scheduler(const Scheduler&) = delete;

    void schedule(Job f, long n);

    void wait();

    virtual ~Scheduler() = default;

private:
    std::condition_variable condition;
    std::mutex mutex;
    size_t size;
    const Error error;
    size_t count{};
};

Scheduler::Scheduler(size_t size, const Error error) : size(size), error(error) {
    if (error == nullptr) {
        throw std::runtime_error("non null error callback required");
    }
}

void Scheduler::schedule(const Job f, long n) {
    std::unique_lock<std::mutex> lock(this->mutex);
    condition.wait(lock, [this] { return this->count < this->size; });
    count++;

    auto job = std::make_shared<Job>(f);

    std::thread thread{
            [n, job, this] {
            std::this_thread::sleep_for(std::chrono::milliseconds(n));

            try {
                (*job)();
            }
            catch (const std::exception& e) {
                this->error(e);
            }
            catch (...) {
                this->error(std::runtime_error("Unknown error"));
            }

            condition.notify_one();
            count--;
        }
    };
    thread.detach();
}

void Scheduler::wait() {
    std::unique_lock<std::mutex> lock(this->mutex);
    condition.wait(lock, [this] { return this->count == 0; });
}

int main() {
    auto start = std::chrono::high_resolution_clock::now();

    Scheduler scheduler(2, [](const std::exception& e) {
        std::cout << "Error: " << e.what() << std::endl;
        });

    scheduler.schedule([] { std::cout << 1 << std::endl; }, 1000);

    scheduler.schedule([] {
        std::cout << 2 << std::endl;
        throw "err";
        }, 150);

    scheduler.schedule([] {
        std::cout << 2 << std::endl;
        throw std::out_of_range("err");
        }, 1500);

    scheduler.schedule([] { std::cout << 3 << std::endl; }, 100);

    scheduler.schedule([] { std::cout << 4 << std::endl; }, 3000);

    scheduler.wait();

    auto stop = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
    std::cout << "Waited: " << duration.count() << std::endl;
}```

Last updated