قوائم المهام لـ C++: من البسيط إلى المعقد
قائمة المهام (Task Queue) هي أحد الأنماط الرئيسية في البرمجة متعددة الخيوط. فهي تسمح بتنظيم التنفيذ غير المتزامن للعمل: خيط أو أكثر من خيوط الموردين يضيفون المهام، ومجموعة من خيوط العمل تقوم بمعالجتها. في لغة C++، تتوفر لهذا الغرض أدوات قياسية ومكتبات متخصصة.
1. القائمة القياسية: std::queue مع الأقفال
أبسط خيار هو استخدام std::queue مع كائن المزامنة (mutex) والمتغير الشرطي. هذا مناسب للمشاريع الصغيرة حيث لا تكون التكاليف الإضافية للمزامنة حرجة.
#include <queue>#include <mutex>#include <condition_variable>
template<typename T>class ThreadSafeQueue { std::queue<T> q_; mutable std::mutex mtx_; std::condition_variable cv_;public: void push(T value) { std::lock_guard<std::mutex> lock(mtx_); q_.push(std::move(value)); cv_.notify_one(); }
T pop() { std::unique_lock<std::mutex> lock(mtx_); cv_.wait(lock, [this]{ return !q_.empty(); }); T val = std::move(q_.front()); q_.pop(); return val; }};المزايا: البساطة، مدمجة في المكتبة القياسية.
العيوب: الأقفال على كل عملية، احتمالية حدوث تنافس (contention) وعكس الأولويات.
2. boost::lockfree::queue — قائمة خالية من الأقفال
توفر مكتبة Boost هياكل بيانات خالية من الأقفال تعتمد على عمليات CAS. boost::lockfree::queue هي قائمة متعددة الخيوط بدون أقفال، تستخدم مجموعة ذاكرة ثابتة أو ديناميكية.
#include <boost/lockfree/queue.hpp>
boost::lockfree::queue<int> queue(128); // حجم ثابت
void producer() { for (int i = 0; i < 1000; ++i) { while (!queue.push(i)) { // إذا كانت القائمة ممتلئة، انتظر أو تجاهل } }}
void consumer() { int value; while (queue.pop(value)) { process(value); }}المزايا: أداء عالٍ للأحجام الصغيرة للقائمة، عدم وجود أقفال.
العيوب: صعوبة التصحيح، حجم محدود (للنسخة الثابتة)، الحاجة إلى استعادة الذاكرة (memory reclamation).
3. Intel TBB (Threading Building Blocks) — tbb::concurrent_queue
Intel TBB هي مكتبة صناعية للبرمجة المتوازية. tbb::concurrent_queue (و tbb::concurrent_bounded_queue) محسّنة للأحمال العالية.
#include <tbb/concurrent_queue.h>
tbb::concurrent_bounded_queue<Task> task_queue;task_queue.set_capacity(1024); // تحديد الحجم
// المنتجtask_queue.push(std::move(task));
// المستهلكTask t;if (task_queue.try_pop(t)) { t.execute();}المزايا: قابلية توسع ممتازة، دعم الأوضاع المحدودة/غير المحدودة، التكامل مع مجدول مهام TBB.
العيوب: ترخيص Apache 2.0 (سابقًا GPL)، الاعتماد على مكتبة TBB بأكملها.
4. libdispatch (Grand Central Dispatch) عبر ربط C++
GCD هو نظام إدارة قوائم من Apple، متاح على macOS/iOS. يوجد غلاف dispatch/queue للغة C++. على Linux يمكن استخدام libdispatch (مفتوح المصدر).
#include <dispatch/dispatch.h>
dispatch_queue_t queue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{ // المهمة 1});
dispatch_async(queue, ^{ // المهمة 2});
dispatch_release(queue);المزايا: إدارة فعالة للخيوط، توسع تلقائي حسب عدد النوى.
العيوب: محدودة