C++ में रिएक्टिव प्रोग्रामिंग: RxCpp और Boost.Signals2 लाइब्रेरीज़ का अवलोकन
रिएक्टिव प्रोग्रामिंग (Reactive Programming) एक प्रतिमान है जो एसिंक्रोनस डेटा स्ट्रीम और परिवर्तनों के प्रसार पर केंद्रित है। C++ में, यह प्रतिमान लाइब्रेरीज़ के माध्यम से कार्यान्वित किया जाता है जो घोषणात्मक तरीके से इवेंट, सिग्नल और एसिंक्रोनस डेटा अनुक्रमों को संसाधित करने की अनुमति देती हैं। इस लेख में, हम C++ में रिएक्टिव प्रोग्रामिंग के लिए दो प्रमुख लाइब्रेरीज़ पर चर्चा करेंगे: RxCpp (Reactive Extensions for C++) और Boost.Signals2। दोनों लाइब्रेरीज़ इवेंट प्रोसेसिंग की समस्या का समाधान करती हैं, लेकिन जटिलता और कार्यक्षमता के विभिन्न स्तरों के साथ।
C++ में रिएक्टिव प्रोग्रामिंग की आवश्यकता क्यों है?
पारंपरिक अनिवार्य कोड अक्सर एसिंक्रोनस इवेंट, उपयोगकर्ता इनपुट, नेटवर्क अनुरोध या मल्टीथ्रेडिंग के साथ काम करते समय जटिल हो जाता है। रिएक्टिव प्रोग्रामिंग प्रदान करता है:
- घोषणात्मक दृष्टिकोण: आप वर्णन करते हैं कि "क्या" होना चाहिए, न कि "कैसे"।
- स्ट्रीम संयोजन: डेटा स्ट्रीम को आसानी से संयोजित, फ़िल्टर और रूपांतरित करना।
- मल्टीथ्रेडिंग प्रबंधन: संदर्भ स्विचिंग और सिंक्रनाइज़ेशन के लिए अंतर्निहित तंत्र।
- त्रुटि प्रबंधन: डेटा और अपवादों के लिए एकीकृत पाइपलाइन।
RxCpp लाइब्रेरी
RxCpp, C++ के लिए रिएक्टिव एक्सटेंशन (Rx) का एक पोर्ट है। यह एसिंक्रोनस डेटा अनुक्रमों के साथ काम करने के लिए ऑपरेटरों का एक शक्तिशाली सेट प्रदान करता है। मुख्य अवधारणाएँ: observable (डेटा स्रोत) और observer (सब्सक्राइबर)।
स्थापना
RxCpp एक header-only लाइब्रेरी है। रिपॉजिटरी को क्लोन करना और हेडर फ़ाइलों को शामिल करना पर्याप्त है:
#include <rxcpp/rx.hpp>using namespace rxcpp;using namespace rxcpp::sources;using namespace rxcpp::operators;उदाहरण 1: संख्याओं की स्ट्रीम पर सरल सब्सक्रिप्शन
एक observable बनाएं जो 1 से 5 तक संख्याएँ उत्पन्न करता है, और उस पर सब्सक्राइब करें:
#include <iostream>#include <rxcpp/rx.hpp>
int main() { auto values = range(1, 5); // observable: 1,2,3,4,5
values. subscribe([](int v) { std::cout << "प्राप्त: " << v << std::endl; }, []() { std::cout << "स्ट्रीम पूर्ण हुई" << std::endl; });
return 0;}उदाहरण 2: फ़िल्टरिंग और रूपांतरण
रिएक्टिव ऑपरेटर डेटा में आसानी से हेरफेर करने की अनुमति देते हैं। सम संख्याओं को फ़िल्टर करें और उन्हें 10 से गुणा करें:
auto values = range(1, 10);
values .filter([](int v) { return v % 2 == 0; }) // केवल सम .map([](int v) { return v * 10; }) // 10 से गुणा करें .subscribe([](int v) { std::cout << "परिणाम: " << v << std::endl; });// आउटपुट: 20, 40, 60, 80, 100उदाहरण 3: स्ट्रीम का विलय
merge ऑपरेटर का उपयोग करके दो स्ट्रीम को मर्ज करें:
auto stream1 = interval(std::chrono::milliseconds(100)).take(3);auto stream2 = interval(std::chrono::milliseconds(150)).take(3);
stream1.merge(stream2) .subscribe([](long v) { std::cout << v << " "; });// संभावित आउटपुट: 0 0 1 2 1 2 (क्रम भिन्न हो सकता है)Boost.Signals2 लाइब्रेरी
Boost.Signals2, सिग्नल और स्लॉट (signals & slots) को लागू करने के लिए एक लाइब्रेरी है। यह Boost लाइब्रेरीज़ का हिस्सा है और कॉलबैक के लिए एक टाइप-सुरक्षित तंत्र प्रदान करती है। RxCpp के विपरीत, Signals2 डेटा स्ट्रीम के साथ काम करने के लिए नहीं है, बल्कि असतत इवेंट को संसाधित करने के लिए है।
मुख्य अवधारणाएँ
- सिग्नल (signal): एक ऑब्जेक्ट जिसे "कॉल" किया जा सकता है और यह अपने सभी सब्सक्राइबर्स को सूचित करेगा।
- स्लॉट (slot): एक फ़ंक्शन या फ़ंक्शनल ऑब्जेक्ट जो सिग्नल से जुड़ा होता है।