مجدول المهام بلغة C++: دليل شامل
مجدول المهام (Task Scheduler) هو أداة قوية تتيح أتمتة تنفيذ الكود في أوقات محددة أو بفترات زمنية محددة. في لغة C++، يتطلب تنفيذ مثل هذا المجدول فهمًا للتعددية الخيطية، والمزامنة، والعمل مع الفواصل الزمنية. في هذه المقالة، سنشرح كيفية إنشاء مجدول مهام خاص بك من الصفر باستخدام المكتبة القياسية للغة C++ (C++11 والإصدارات الأحدث).
المكونات الأساسية للمجدول
يتكون أي مجدول مهام من عدة عناصر رئيسية:
- مخزن المهام — قائمة انتظار أو حاوية لتخزين المهام المجدولة.
- المؤقت — آلية تحدد متى يجب تنفيذ المهمة.
- مجموعة الخيوط — للتنفيذ المتوازي للمهام دون حظر الخيط الرئيسي.
- آلية الإلغاء — إمكانية إلغاء مهمة قبل تنفيذها.
تنفيذ بسيط لمجدول بخيط واحد
لنبدأ بمثال أساسي حيث يتم تنفيذ المهام بشكل تسلسلي في خيط خلفية:
#include <iostream>#include <thread>#include <chrono>#include <functional>#include <queue>#include <mutex>#include <condition_variable>
class TaskScheduler {public: // يجدول مهمة بتأخير void schedule(std::function<void()> task, int delay_ms) { std::lock_guard<std::mutex> lock(mutex_); tasks_.push({std::chrono::steady_clock::now() + std::chrono::milliseconds(delay_ms), task}); cv_.notify_one(); }
// يبدأ المجدول في خيط منفصل void start() { worker_ = std::thread([this]() { while (!stop_) { std::unique_lock<std::mutex> lock(mutex_); if (tasks_.empty()) { cv_.wait(lock, [this]() { return !tasks_.empty() || stop_; }); } if (stop_) break;
auto now = std::chrono::steady_clock::now(); auto& top = tasks_.top(); if (top.time <= now) { auto task = top.task; tasks_.pop(); lock.unlock(); task(); // تنفيذ المهمة } else { cv_.wait_until(lock, top.time); } } }); }
void stop() { stop_ = true; cv_.notify_all(); if (worker_.joinable()) worker_.join(); }
private: struct Task { std::chrono::steady_clock::time_point time; std::function<void()> task; bool operator>(const Task& other) const { return time > other.time; } };
std::priority_queue<Task, std::vector<Task>, std::greater<Task>> tasks_; std::mutex mutex_; std::condition_variable cv_; std::thread worker_; bool stop_ = false;};
int main() { TaskScheduler scheduler; scheduler.start();
scheduler.schedule([]() { std::cout << "تم تنفيذ المهمة 1 بعد ثانيتين"; }, 2000);
scheduler.schedule([]() { std::cout << "تم تنفيذ المهمة 2 بعد ثانية واحدة"; }, 1000);
std::this_thread::sleep_for(std::chrono::seconds(3)); scheduler.stop(); return 0;}مجدول مع مجموعة خيوط للتنفيذ المتوازي
للسيناريوهات الأكثر تعقيدًا، حيث قد تستغرق المهام وقتًا طويلاً، من الأفضل استخدام مجموعة خيوط. إليك مثال مع مجموعة خيوط صغيرة:
#include <vector>#include <queue>#include <thread>#include <mutex>#include <condition_variable>#include <f