cppadvanced90 minutes

Advanced C++ Mini-Project: Multi-Threaded Task Scheduler with Prioritization

Build an advanced multi-threaded task scheduler in C++ that accepts tasks with different priorities, efficiently manages a thread pool, and executes tasks in priority order. The scheduler should support adding, cancelling, and monitoring tasks in real-time.

Challenge prompt

Create a multi-threaded task scheduler class in C++ with the following requirements: 1. The scheduler manages a fixed-size thread pool created at initialization. 2. Users can submit tasks (as std::function<void()>) with an integer priority (higher number = higher priority). 3. The scheduler maintains a priority queue of pending tasks and ensures higher priority tasks are executed first. 4. Provide methods to add new tasks, cancel pending tasks by ID, and query the status of submitted tasks. 5. The scheduler should handle concurrent submissions and safe shutdown. Implement the scheduler ensuring thread safety, proper synchronization, and efficient execution without busy waiting.

Guidance

  • Use a thread-safe priority queue structure to manage tasks based on priority.
  • Synchronize access to shared resources using mutexes and condition variables.
  • Design task IDs and status tracking for cancellation and monitoring.
  • Gracefully handle shutdown to join all worker threads without losing tasks.

Hints

  • Consider std::priority_queue for managing tasks sorted by priority alongside a custom comparator.
  • Use std::mutex and std::condition_variable to control access and coordinate worker threads waiting for tasks.
  • Assign unique IDs to tasks upon submission using atomic counters for easy tracking and cancellation.

Starter code

#include <iostream>
#include <queue>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <unordered_map>

class TaskScheduler {
public:
    TaskScheduler(size_t numThreads);
    ~TaskScheduler();

    int submitTask(std::function<void()> task, int priority);
    bool cancelTask(int taskId);
    bool isTaskRunning(int taskId);
    void shutdown();

private:
    struct Task {
        int id;
        int priority;
        std::function<void()> func;
        bool operator<(const Task& other) const {
            // For priority queue: higher priority should come first
            return priority < other.priority;
        }
    };

    void workerThread();

    std::priority_queue<Task> taskQueue;
    std::unordered_map<int, bool> runningTasks;
    std::mutex mtx;
    std::condition_variable cv;
    std::vector<std::thread> workers;
    std::atomic<int> nextTaskId;
    bool shuttingDown;
};

// Implementations of methods to be done by the user

Expected output

The program will successfully schedule and execute tasks with correct prioritization, outputting task execution order that matches descending priority, and demonstrate task cancellation and monitoring features.

Core concepts

multithreadingthread synchronizationpriority queuetask schedulingconcurrent programming

Challenge a Friend

Send this duel to someone else and see if they can solve it.