C++ में टास्क शेड्यूलर: आर्किटेक्चर, कार्यान्वयन और उदाहरण
\n\nटास्क शेड्यूलर आधुनिक उच्च-लोड सिस्टम, गेम इंजन, एप्लिकेशन सर्वर और एम्बेडेड उपकरणों के प्रमुख घटकों में से एक है। इस लेख में, हम विस्तार से समझेंगे कि भाषा की मानक लाइब्रेरी का उपयोग करके C++ में स्क्रैच से अपना स्वयं का टास्क शेड्यूलर कैसे बनाया जाए। आप जानेंगे कि टास्क क्यू कैसे काम करता है, टाइमर कैसे काम करते हैं, थ्रेड को कैसे सिंक्रोनाइज़ करें और सामान्य गलतियों से कैसे बचें।
\n\nटास्क शेड्यूलर की आवश्यकता क्यों है?
\nटास्क शेड्यूलर निम्नलिखित की अनुमति देता है:
\n- \n
- बैकग्राउंड थ्रेड में एसिंक्रोनस रूप से कोड निष्पादित करना; \n
- विलंब और आवधिक रन सेट करना; \n
- निष्पादन के प्राथमिकता और क्रम को प्रबंधित करना; \n
- CPU संसाधनों के उपयोग को अनुकूलित करना। \n
सरल std::thread के विपरीत, शेड्यूलर निष्पादन पर लचीला नियंत्रण प्रदान करता है और प्रत्येक कार्य के लिए थ्रेड बनाने से बचने में मदद करता है।
मूल आर्किटेक्चर
\nकिसी भी शेड्यूलर में तीन मुख्य भाग होते हैं:
\n- \n
- टास्क क्यू — कार्य वस्तुओं (फ़ंक्शन, आर्गुमेंट, मेटाडेटा) को संग्रहीत करता है; \n
- थ्रेड पूल — एक या अधिक वर्किंग थ्रेड जो क्यू से कार्य निकालते हैं और उन्हें निष्पादित करते हैं; \n
- टाइमर / टाइम शेड्यूलर — निष्पादन में देरी करने या शेड्यूल पर कार्य चलाने की अनुमति देता है। \n
C++ में टास्क क्यू का कार्यान्वयन
\nशुरुआत में, कार्य की संरचना को परिभाषित करते हैं:
\nstruct 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 का उपयोग करते हैं:
#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 पुस्तकालय में भी
Moshi Kotlin: पूर्ण गाइड उदाहरणों के साथ
Go (Golang) के लिए सर्वश्रेष्ठ लॉगिंग लाइब्रेरीज़: समीक्षा और तुलना
Kotlin में Excel के साथ कार्य: Apache POI लाइब्रेरी और Kotlin रैपर
Prometheus मेट्रिक्स C# (.NET) में: एकीकरण और कॉन्फ़िगरेशन