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 userExpected 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
Challenge a Friend
Send this duel to someone else and see if they can solve it.