2012-04-01 15 views
6

मैंने buffered नेटवर्क सॉकेट I/O, अंडरफ्लो, ओवरफ़्लो, और सिंक ओवरराइड करने के लिए एक कस्टम स्ट्रीमबफ लिया है ताकि अंडरफ्लो दूसरे दो के सेट के साथ पारस्परिक रूप से थ्रेड-सुरक्षित हो, (मेरे पास अलग इनपुट और आउटपुट आंतरिक बफर हैं) । यह ठीक काम करता है, लेकिन मैं इसे पूर्ण डुप्लेक्स I/O के लिए उपयोग करना चाहता हूं, जहां एक थ्रेड इनपुट कर रहा है, जबकि कोई अन्य आउटपुट कर रहा है, इसलिए मैं नेटवर्क भेजने के दौरान प्राप्त करने के लिए प्राप्त थ्रेड और ओस्ट्रीम के लिए एक आईट्रीम का उपयोग करना चाहता हूं स्ट्रीमबफ के रूप में सभी सॉकेट सामान सार तत्व। मेरा सवाल यह है कि इनपुट और आउटपुट बफर अलग होने पर ओस्ट्रीम पर आउटपुट ऑपरेशंस से प्रभावित स्ट्रीमबफ सदस्यों से इन्सट्रीम विघटन पर इनपुट ऑपरेशंस द्वारा इनपुट ऑपरेशन से प्रभावित कितने हद तक हैं?आईप्रीम और ओस्ट्रीम साझा स्ट्रीमबफ परस्पर थ्रेड-सुरक्षित डुप्लेक्स I/O के लिए सुरक्षित है?

यह मेरे स्ट्रीमबफ अमूर्तता से सॉकेट सामान को अलग करने के बजाय ऐसा करने में सक्षम होना बेहतर होगा, इसलिए सॉकेट को अलग-अलग स्ट्रीमबफ के साथ आईट्रीम और ओस्ट्रीम के बीच साझा किया जा सकता है - फिर मुझे दो संस्करणों की भी आवश्यकता होगी स्ट्रीमबफ - एक एकल बफर के साथ (केवल इस्ट्रीम में या केवल ओस्ट्रीम में उपयोग के लिए), और मेरे पास अब दो आंतरिक बफर के साथ, Iostream में उपयोग के लिए ... अतिरिक्त कक्षाओं और कोड डुप्लिकेशन के रूप में बेकार है।

+0

पहली नज़र में मुझे कुछ संदेह थे, लेकिन यह कुछ समय में मैंने देखा सबसे अच्छा सवाल जैसा दिखता है। +1 – Potatoswatter

उत्तर

2

std::streambuf (या std::basic_streambuf<...>) के लिए कोई विशेष गारंटी नहीं दी गई है जो आमतौर पर दी जाने वाली चीज़ों की तुलना में अधिक गारंटी देता है। यही है, आप किसी भी समय ऑब्जेक्ट की स्थिति को पढ़ने वाले कई धागे प्राप्त कर सकते हैं, लेकिन यदि ऑब्जेक्ट की स्थिति को संशोधित करने वाला एक थ्रेड है तो ऑब्जेक्ट तक पहुंचने वाला कोई अन्य थ्रेड नहीं होगा। दोनों पाठ पढ़ने और लिखने के लिए स्ट्रीम बफर के राज्य को संशोधित करते हैं, यानी औपचारिक दृष्टिकोण से आप बाहरी सिंक्रनाइज़ेशन के बिना उनका उपयोग नहीं कर सकते हैं।

आंतरिक रूप से दो बफर पूरी तरह से अलग हैं और एक दूसरे के साथ कुछ लेना देना नहीं है। स्ट्रीम बफर पर किए गए संचालन उन्हें एक संरचित तरीके से संशोधित करते हैं और मैं कल्पना नहीं कर सकता कि किसी भी कार्यान्वयन में पॉइंटर्स के दो सेटों के बीच एक स्पष्ट बातचीत होगी। व्यावहारिक रूप से, मुझे नहीं लगता कि पढ़ने और लिखने के बीच कोई सिंक्रनाइज़ेशन आवश्यक है। हालांकि, मुझे इससे पहले एहसास नहीं हुआ था कि बफर पॉइंटर्स के दो सेट वास्तव में एक ही कैश लाइन साझा कर सकते हैं जो कम से कम प्रदर्शन समस्याओं का कारण बन सकता है। मुझे नहीं लगता कि इससे किसी भी शुद्धता की समस्या होनी चाहिए।

संभवतः दो स्ट्रीम बफर के बीच साझा किया जाने वाला एकमात्र संसाधन std::locale ऑब्जेक्ट है जो स्थिर है, हालांकि। इसके अलावा, std::streambuf इस ऑब्जेक्ट का कोई भी उपयोग नहीं करता है: यह आपका स्ट्रीम बफर है जो कुछ पहलुओं का उपयोग कर सकता है (उदा। std::codecvt<...> पहलू)। चूंकि लोकेल को वर्चुअल फ़ंक्शन imbue() पर कॉल के माध्यम से बदला जाता है, इसलिए आप इस परिवर्तन को रोक सकते हैं और यदि आपका स्ट्रीम बफर लोकेल का उपयोग करता है तो जो भी सिंक्रनाइज़ेशन की आवश्यकता होती है।

संक्षेप में, मानक कोई गारंटी नहीं देता है कि यह समान धारा बफर का उपयोग करके पढ़ने और लिखने के लिए समवर्ती धागे का उपयोग करने के लिए काम करेगा।व्यावहारिक रूप से, डीएस 9 के शायद एकमात्र सिस्टम है जहां यह असफल हो जाएगा और साझा किए गए कैश लाइनों में समाप्त होने वाले बफर पॉइंटर्स के कारण दो थ्रेड प्रभावी ढंग से सिंक्रनाइज़ हो सकते हैं।

+0

" ... std :: लोकेल ऑब्जेक्ट जो स्टेटलेस होना है ... " - ध्यान देने योग्य है कि उसे दो 'mbstate_t' सदस्यों की आवश्यकता है, जो इनपुट और आउटपुट के लिए अलग हैं। DS9k क्या है? – Potatoswatter

+0

[डेथ स्टेशन 9000 (डीएस 9 के)] (http://en.wikipedia.org/wiki/User:CompuHacker/CHDS9000) मानक के संभावित कार्यान्वयन के रूप में एक कल्पित और जानबूझकर अनुपयोगी है: जहां किसी भी स्वतंत्रता को दिया जाता है, यह संभवतः जितना संभव हो उतना नुकसान पहुंचाने के लिए इसका उपयोग करता है। –

+0

मुझे लगता है कि आईट्रीम में सिंक() सदस्य है, जो स्ट्रीमबफ की सिंक को कॉल करेगा ()। मैंने किसी के बारे में कुछ भी नहीं देखा है आईट्रीम कॉलिंग सिंक() स्वयं के अन्य सदस्य, इसलिए मुझे लगता है कि यह केवल एक मुद्दा है यदि उपयोगकर्ता इसे कॉल करता है, और मैं इसे कुछ भी करने के लिए ओवरराइड कर सकता हूं या स्ट्रीमबफ को सॉकेट से बफर में कुछ और डेटा पढ़ने की कोशिश कर सकता हूं । –

2

इनपुट और आउटपुट अनुक्रम अनिवार्य रूप से स्वतंत्र हैं। वहाँ cppreference.com में एक अच्छा चित्र है:

Diagram of streambuf members

केवल एक चीज इनपुट और आउटपुट दृश्यों के बीच साझा locale वस्तु जो पाठ एन्कोडिंग अनुवाद प्रदर्शन किया codecvt पहलू होता है।

सिद्धांत रूप में, पाठ एन्कोडिंग मध्यरात्रि को बदलना थ्रेड-असुरक्षित होगा, लेकिन व्यवहार में पुस्तकालय किसी भी तरह से उस ऑपरेशन का समर्थन नहीं करते हैं!

आपको जाने के लिए अच्छा होना चाहिए।

+0

स्थानीय मध्यरात्रि को बदलने से असंगत व्यवहार होता है (कम से कम कोडकैट के लिए यह इनपुट/आउटपुट के एक हिस्से के मध्य अनुवाद (do_in/do_out) में हो सकता है)। इसलिए किसी भी स्ट्रीम को पढ़ने/लिखने के बाद स्थानीय को बदलना एक बुरा विचार जैसा प्रतीत होता है। इसका एक परिणाम यह है कि stream_buf वर्ग व्युत्पन्न कक्षाओं को स्थानीय लोगों से प्राप्त किए गए पहलू मूल्यों को कैश करने की अनुमति देता है। इसके अलावा कुछ धाराएं स्थानीय लोगों को बदलने पर प्रतिबंध/शर्तों को डालती हैं यदि वे शुरुआत में नहीं हैं (यानी पढ़ने/लिखने के बाद)। –

+0

@ लोकी: लोकेल मध्यरात्रि को बदलना फ़ाइल को बंद करने और इसे एक अलग लोकेल के साथ फिर से खोलना है। कोई वैचारिक बाधा नहीं है; एक अपवाद में एक अवैध अनुक्रम परिणाम लिखना। यह मानक द्वारा समर्थित है लेकिन कुछ कार्यान्वयन के जरिए कुछ। – Potatoswatter

+0

मुझे मानक में imbue() या pubimbue() का उपयोग करते समय स्ट्रीम खोलने और बंद करने का कोई संदर्भ नहीं दिखता है। जैसा कि मैंने ऊपर बताया है वैचारिक बाधाएं हैं। –