C++ में टास्क शेड्यूलर: स्क्रैच से Task Scheduler बनाना

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

C++ में टास्क शेड्यूलर: आर्किटेक्चर, कार्यान्वयन और उदाहरण

\n\n

टास्क शेड्यूलर आधुनिक उच्च-लोड सिस्टम, गेम इंजन, एप्लिकेशन सर्वर और एम्बेडेड उपकरणों के प्रमुख घटकों में से एक है। इस लेख में, हम विस्तार से समझेंगे कि भाषा की मानक लाइब्रेरी का उपयोग करके C++ में स्क्रैच से अपना स्वयं का टास्क शेड्यूलर कैसे बनाया जाए। आप जानेंगे कि टास्क क्यू कैसे काम करता है, टाइमर कैसे काम करते हैं, थ्रेड को कैसे सिंक्रोनाइज़ करें और सामान्य गलतियों से कैसे बचें।

\n\n

टास्क शेड्यूलर की आवश्यकता क्यों है?

\n

टास्क शेड्यूलर निम्नलिखित की अनुमति देता है:

\n
    \n
  • बैकग्राउंड थ्रेड में एसिंक्रोनस रूप से कोड निष्पादित करना;
  • \n
  • विलंब और आवधिक रन सेट करना;
  • \n
  • निष्पादन के प्राथमिकता और क्रम को प्रबंधित करना;
  • \n
  • CPU संसाधनों के उपयोग को अनुकूलित करना।
  • \n
\n

सरल std::thread के विपरीत, शेड्यूलर निष्पादन पर लचीला नियंत्रण प्रदान करता है और प्रत्येक कार्य के लिए थ्रेड बनाने से बचने में मदद करता है।

\n\n

मूल आर्किटेक्चर

\n

किसी भी शेड्यूलर में तीन मुख्य भाग होते हैं:

\n
    \n
  • टास्क क्यू — कार्य वस्तुओं (फ़ंक्शन, आर्गुमेंट, मेटाडेटा) को संग्रहीत करता है;
  • \n
  • थ्रेड पूल — एक या अधिक वर्किंग थ्रेड जो क्यू से कार्य निकालते हैं और उन्हें निष्पादित करते हैं;
  • \n
  • टाइमर / टाइम शेड्यूलर — निष्पादन में देरी करने या शेड्यूल पर कार्य चलाने की अनुमति देता है।
  • \n
\n\n

C++ में टास्क क्यू का कार्यान्वयन

\n

शुरुआत में, कार्य की संरचना को परिभाषित करते हैं:

\n
struct Task {\n    std::function<void()> func;\n    std::chrono::steady_clock::time_point executeAt;\n    size_t id;\n};
\n

क्यू को थ्रेड-सेफ होना चाहिए। हम std::priority_queue (ताकि कम निष्पादन समय वाले कार्य पहले निकाले जाएं) और सिंक्रोनाइज़ेशन के लिए std::mutex का उपयोग करते हैं:

\n
#include <queue>\n#include <mutex>\n#include <condition_variable>\n#include <functional>\n#include <chrono>\n#include <thread>\n#include <vector>\n\nclass TaskScheduler {\npublic:\n    explicit TaskScheduler(size_t threadCount = std::thread::hardware_concurrency()) {\n        for (size_t i = 0; i < threadCount; ++i) {\n            workers.emplace_back([this] { workerLoop(); });\n        }\n    }\n\n    ~TaskScheduler() {\n        stop();\n    }\n\n    // विलंब के साथ कार्य जोड़ें\n    template<typename F, typename... Args>\n    void schedule(F&& f, Args&&... args, std::chrono::milliseconds delay = std::chrono::milliseconds(0)) {\n        auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);\n        Task t{std::move(task), std::chrono::steady_clock::now() + delay, nextId++};\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            queue.push(std::move(t));\n        }\n        cv.notify_one();\n    }\n\n    void stop() {\n        {\n            std::lock_guard<std::mutex> lock(mutex);\n            stopping = true;\n        }\n        cv.notify_all();\n        for (auto& worker : workers) {\n            if (worker.joinable()) worker.join();\n        }\n    }\n\nprivate:\n    struct Task {\n        std::function<void()> func;\n        std::chrono::steady_clock::time_point executeAt;\n        size_t id;\n\n        bool operator>(const Task& other) const {\n            return executeAt > other.executeAt;\n        }\n    };\n\n    void workerLoop() {\n        while (true) {\n            std::unique_lock<std::mutex> lock(mutex);\n            cv.wait(lock, [this] { return stopping || !queue.empty(); });\n            if (stopping && queue.empty()) return;\n\n            if (!queue.empty()) {\n                auto top = queue.top();\n                if (std::chrono::steady_clock::now() >= top.executeAt) {\n                    queue.pop();\n                    lock.unlock();\n                    top.func                    

अनुशंसाएँ