2008-11-07 18 views
20

मुझे एक एप्लिकेशन लिख रहा है जो दो istreams से इनपुट पर ब्लॉक करता है।अवरुद्ध बूस्ट :: थ्रेड

istream से पढ़ना एक सिंक्रोनस (अवरुद्ध) कॉल है, इसलिए, मैंने पढ़ने के लिए दो Boost::thread एस बनाने का निर्णय लिया।

या तो इनमें से एक थ्रेड "अंत" (प्राप्त कुछ इनपुट के आधार पर) तक पहुंच सकता है, और एक बार "अंत" पहुंचने के बाद, दोनों इनपुट स्ट्रीम प्राप्त करना बंद कर देते हैं। दुर्भाग्यवश, मुझे नहीं पता कि यह कौन करेगा।

इस प्रकार, मैं दोनों धागे पर join() नहीं कर सकता, क्योंकि केवल एक थ्रेड (जिसे पूर्व निर्धारित नहीं किया जा सकता) वास्तव में वापस आ जाएगा (अनब्लॉक)।

मुझे किसी अन्य तरह से बाहर निकलने के लिए मजबूर होना चाहिए, लेकिन यह इनपुट के लिए इंतजार कर रहा है, इसलिए यह स्वयं तय नहीं कर सकता कि यह वापस आने का समय है (हालत चर या क्या नहीं)।

उनके एक तरह से या तो करने के लिए है:

  • एक संकेत को बढ़ावा :: धागा, या
  • एक istream "असफल" करने के लिए बाध्य करें भेजें, या
  • एक बूस्ट :: धागा मार?

नोट:

  • istreams में से एक cin
  • मैं इस प्रक्रिया को पुनः आरंभ करने की कोशिश कर रहा हूँ, इसलिए मैं बंद नहीं कर सकते इनपुट एक तरह से की अनुमति नहीं देतीं कि उन्हें reseting में धाराओं।

संपादित करें:

  • मैं जब "अंत" तक पहुँच जाता है पता है, और मुझे पता है जो धागा सफलतापूर्वक समाप्त हो गया है, और जो मारे जाने की जरूरत है। इसकी हत्या मुझे समझने की जरूरत है (या एक आइसट्रीम से पढ़ने के लिए एक अलग रणनीति)।
  • मैं दोनों धागे की जरूरत से बाहर निकलें और ठीक से सफाई :(को

धन्यवाद!

उत्तर

4

मुझे नहीं लगता कि इसमें क्रॉस प्लेटफॉर्म करने के लिए एक तरीका है, लेकिन pthread_cancel होना चाहिए कि आप क्या देख रहे हैं । एक बढ़ावा धागा के साथ आप एक धागे से native_handle प्राप्त कर सकते हैं, और उस पर pthread_cancel कहते हैं।

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

+0

सौभाग्य से मैं अब के लिए एक लिनक्स मशीन के लिए विकास कर रहा हूं, लेकिन एक पोर्टेबल संस्करण पसंद करूंगा। इसके लिए धन्यवाद! – mmocny

+0

pthread_cancel() इसे एक समान परिदृश्य में मेरे लिए नहीं बना रहा है, यहां तक ​​कि इसके रद्दीकरण प्रकार को ASYNCHRONOUS में भी सेट नहीं किया गया है। – gatopeich

0

अपने धागे को मारने की कोशिश करने के बजाय, आप हमेशा इसके बजाय धागे को आजमा सकते हैं, और यदि यह विफल हो जाता है, तो आप इसके बजाय दूसरे में शामिल हो जाते हैं। (मान लीजिए कि आप हमेशा अपने दो धागे में से एक में शामिल होने में सक्षम होंगे)।

बढ़ावा में: थ्रेड आप timed_join फ़ंक्शन की तलाश में हैं।

यदि आप सही उत्तर देखना चाहते हैं, तो, समय-समय पर प्रतीक्षा के साथ गैर-अवरुद्ध आईओ का उपयोग करना होगा। एसिंक्रोनस आईओ के गैर-अवरुद्ध होने के साथ, आपको सिंक्रोनस आईओओ की प्रवाह संरचना प्राप्त करने की अनुमति है।

आप एक आईट्रीम बनाने के बारे में बात करते हैं, लेकिन एक आईट्रीम केवल एक इंटरफ़ेस है। stdin के लिए, आप केवल पढ़ने में बाधा डालने के लिए stdin फ़ाइल descriptor fclose कर सकते हैं। दूसरे के लिए, यह उस स्थान पर निर्भर करता है जहां से आप पढ़ रहे हैं ...

+0

यह कैसे करें इस पर कोई सुझाव? मैं इस धारणा के तहत था कि यह असंभव था (पोर्टेबल रूप से ऐसा करने के लिए) सीन के साथ। और मैंने पहले ही उल्लेख किया है कि मैं एक धागे को ठीक से शामिल कर रहा हूं, दूसरा जिसकी मुझे निपटने की ज़रूरत है। हालांकि धन्यवाद। – mmocny

+0

एक बार फिर, धन्यवाद। लेकिन मुझे लगता है कि आप इस सवाल को गलत समझ रहे हैं। धागे में से एक कभी शामिल नहीं होगा()। मुझे पता है कि धागे में से एक को कैसे शामिल किया जाए, और उस व्यक्ति की पहचान कैसे करें जो नहीं करता है। मुझे अन्य थ्रेड को अनब्लॉक करने के लिए क्या चाहिए। (या एक अलग समाधान के साथ आते हैं) – mmocny

0

विंडोज के तहत, एक अपवाद फेंकने वाली एक पंक्ति को कतार करने के लिए QueueUserAPC का उपयोग करें। वह दृष्टिकोण मेरे लिए ठीक काम करता है।

हाउवर: मैंने पाया है कि बूस्ट म्यूटेक्स आदि Win32 पर "सतर्क" नहीं हैं, इसलिए QueueUserAPC उन्हें बाधित नहीं कर सकता है।

1

लिनक्स पर, मैं pthread_signal (SIGUSR1) का उपयोग करता हूं, क्योंकि यह आईओ अवरुद्ध करता है। विंडोज़ पर ऐसी कोई कॉल नहीं है जैसा कि मैंने अपना कोड पोर्ट करते समय खोजा था। सॉकेट रीडिंग कॉल में केवल एक बहिष्कृत। विंडोज़ में आपको स्पष्ट रूप से ऐसी घटना को परिभाषित करना होगा जो आपके अवरुद्ध कॉल को बाधित करेगा। तो आईओ अवरुद्ध करने में बाधा डालने के लिए एक सामान्य तरीका के रूप में ऐसी कोई चीज नहीं है (AFAIK)।

बूस्ट.थ्रेड डिज़ाइन अच्छी तरह से पहचाने गए इंटरप्ट पॉइंट्स प्रबंधित करके इसे संभालता है। मैं boost.asio अच्छी तरह से नहीं जानता और ऐसा लगता है कि आप वैसे भी इस पर भरोसा नहीं करना चाहते हैं। यदि आप गैर-अवरुद्ध प्रतिमान का उपयोग करने के लिए रिफैक्टर नहीं करना चाहते हैं, तो आप जो भी कर सकते हैं वह गैर-अवरुद्ध (मतदान) और आईओ को अवरुद्ध करने के बीच कुछ उपयोग कर रहा है। (? छद्म कोड):

while(!stopped && !interrupted) 
{ 
    io.blockingCall(timeout); 
    if(!stopped && !interrupted) 
    { 
     doSomething(); 
    } 
} 

तो फिर आप अपने दो धागे को बाधित और उन्हें शामिल होने के ...

शायद यह आपके मामले में सरल है कि ऐसा कुछ करना है? यदि आपके पास एक मास्टर थ्रेड है जो जानता है कि एक थ्रेड समाप्त हो गया है तो आपको अन्य थ्रेड के आईओ को बंद करना होगा?

संपादित करें: तरह से मैं अंतिम समाधान आप में दिलचस्पी रखता हूँ रखकर ...

0

यह धागे तुम क्या आप एक सरल तरीके से चाहते हैं की मदद नहीं कर रहे हैं कि लगता है। यदि Boost.Asio आपकी पसंद नहीं है, तो select() का उपयोग करने पर विचार करें।

विचार दो फाइल डिस्क्रिप्टर प्राप्त करना है और select() का उपयोग करने के लिए आपको बताएं कि उनमें से कौन सा इनपुट उपलब्ध है। cin के लिए फ़ाइल डिस्क्रिप्टर आमतौर पर STDIN_FILENO है; दूसरा कैसे प्राप्त करें अपने विनिर्देशों पर निर्भर करता है (यदि यह एक फ़ाइल है, तो ifstream का उपयोग करने के बजाय open())।

एक लूप में select() पर कॉल करें, यह जानने के लिए कि कौन सा इनपुट पढ़ना है, और जब आप रुकना चाहते हैं, तो बस लूप से बाहर निकलें।

4

हां वहाँ है!

boost::thread::terminate() आपके विनिर्देशों के लिए काम करेगा।

इससे लक्षित धागे को अपवाद फेंकने का कारण बन जाएगा। मान लीजिए कि यह बेकार है, ढेर सभी संसाधनों को ठीक से नष्ट कर देगा और थ्रेड निष्पादन को समाप्त कर देगा।

समाप्ति तत्काल नहीं है। (वैसे भी गलत धागा चल रहा है, वैसे भी।)

यह पूर्वनिर्धारित स्थितियों के तहत होता है - संभवतः आपके लिए सबसे सुविधाजनक boost::this_thread::sleep(); पर कॉल करते समय, जो आप उस थ्रेड को आवधिक रूप से कर सकते हैं।

+0

आप किस बारे में बात कर रहे हैं? __boost__ में ऐसा कोई फ़ंक्शन नहीं है 'boost :: thread :: terminate() '। –

+1

हाय, @YagamyLight। मुझे यकीन नहीं है कि क्या आप वास्तव में एक जवाब चाहते हैं, लेकिन आप इस उत्तर के बाद 'बूस्ट :: थ्रेड :: टर्मिनेट' के बारे में एक प्रश्न पोस्ट करने के लिए स्वतंत्र हैं। –

4

यदि कोई बूस्ट थ्रेड आई/ओ ऑपरेशन पर अवरुद्ध हो रहा है (उदा। cin>>whatever), boost::thread::terminate() धागे को नहीं मारेंगे। cin i/o मान्य समाप्ति बिंदु नहीं है। कैच 22.

1

मैं ने वही समस्या अपने आप को था और इस समाधान है, जो इस सवाल के कुछ अन्य पाठकों उपयोगी लग सकते पर पहुँच गए हैं:

यह मानते हुए कि आप एक प्रतीक्षा() कमांड के साथ एक शर्त चर का उपयोग कर रहे हैं, यह आपके लिए यह जानना महत्वपूर्ण है कि बूस्ट में, प्रतीक्षा() कथन एक प्राकृतिक बाधा बिंदु है। तो बस प्रतीक्षा कथन के साथ कोड के चारों ओर एक कोशिश/पकड़ ब्लॉक डालें और फ़ंक्शन को आपके कैच ब्लॉक में सामान्य रूप से समाप्त करने दें।

अब, मान लें कि आपके थ्रेड पॉइंटर्स के साथ एक कंटेनर है, अपने थ्रेड पॉइंटर्स पर फिर से चालू करें और प्रत्येक थ्रेड पर इंटरप्ट() को कॉल करें, इसके बाद जुड़ें()।

अब आपके सभी धागे सुन्दर तरीके से समाप्त हो जाएंगे और किसी भी बूस्ट से संबंधित मेमोरी क्लीनअप को साफ-सफाई करना चाहिए।

0

बहुत देर हो चुकी है, लेकिन विंडोज़ में (और यह उन चीजों को पुनर्जीवित करने वालों के लिए वीएमएस या आरएसएक्स जैसे अग्रदूत हैं) मैं रीडफाइलएक्स जैसे कुछ पूरा करने के साथ उपयोग करता हूं जो समाप्त होने पर संकेत करता है, और अगर रद्द करने की आवश्यकता है तो रद्द करें जल्दी।

लिनक्स/बीएसडी में एक पूरी तरह से अलग अंतर्निहित एपीआई है जो लचीला नहीं है। सिग्नल भेजने के लिए pthread_kill का उपयोग करना मेरे लिए काम करता है, जो पढ़ने/खुले ऑपरेशन को रोक देगा।

प्रत्येक प्लेटफार्म, आईएमएचओ के लिए इस क्षेत्र में अलग-अलग कोड लागू करने के लायक है।

संबंधित मुद्दे