2014-09-06 22 views
10

को अवरुद्ध नहीं करता है मेरे पास एक बहुप्रचारित एप्लिकेशन है, जिसमें उपयोगकर्ता इनपुट के लिए मुख्य थ्रेड के रूप में प्रतीक्षा करने वाला लूप है। सही इनपुट पर, यह लूप को रोकना और अन्य सभी धागे के लिए प्रतीक्षा करना है, ताकि अंततः समाप्त हो सके।std :: सूची <std::future> विनाशक

इस प्रयोजन के लिए मैं एक std :: सूची जिसमें मैं एसटीडी डाल :: भविष्य वस्तुओं धागा निर्माण के लिए

std::list<std::future<int>> threads; 
threads.emplace_front(std::async(std::launch::async, ...)); 

मैं यह धारणा थी बनाया बनाया है, कि दे सूची गुंजाइश से बाहर निकलता है, तब तक ब्लॉक करना चाहिए जब तक कि सभी धागे अपने मुख्य कार्य को वापस न करें, क्योंकि सूची एस विनाशक std :: भविष्य तत्वों और the destructor of those थ्रेड समाप्त होने के लिए प्रतीक्षा करेगा।

संपादित करें: चूंकि यह प्रासंगिक है मैं इसे यहाँ जोड़ देगा:, यह दृश्य स्टूडियो में MSVC संस्करण 2013 व्यावसायिक /संपादित करें

साथ Win7 पर है जब मैं इस कोशिश की उसने ऐसा नहीं किया ब्लॉक, मुझे

for (auto it = threads.begin(); it != threads.end(); ++it) { 
    it->get(); 
} 

फ़ंक्शन के अंत में सही ढंग से ब्लॉक करने के लिए जोड़ना था।

क्या मुझे कुछ गलत समझना पड़ा, या क्या मुझे धागे को अलग तरीके से बनाना है, जो मैं यहां करना चाहता हूं?

+0

@ टी.सी.आईफ़ यह वास्तव में इतना आसान है, और मुझे उन पर भरोसा नहीं करना चाहिए, आपको इसे एक उत्तर के रूप में जोड़ना चाहिए, इसलिए मैं इसे स्वीकार कर सकता हूं – Ongy

+4

एक बग की तरह दिखता है। कंपाइलर क्या है? – ixSci

+0

हम्म, स्कॉट मेयर्स [एक अच्छा तर्क देता है] (http://scottmeyers.blogspot.com/2013/03/stdfutures-from-stdasync-arent-special.html) कि 'std :: async' के विनिर्देश के लिए इसकी आवश्यकता है रुकावट के लिए। दिलचस्प ... –

उत्तर

12

यह MSVC bug that has been fixed है, लेकिन यह तब तक उपलब्ध नहीं होगा जब तक कि एमएस विजुअल सी ++ का एक नया संस्करण रिलीज़ न हो, शायद 2015 में कुछ समय। (यह भी available in the CTP for the new version है, लेकिन किसी भी उत्पादन के लिए इसका उपयोग करना एक बहुत बुरा विचार है कोड ...)

स्कॉट Meyers के रूप में his blog post में बताया गया है, एक std::futurelaunch::async नीति का उपयोग कर एक std::async कॉल द्वारा वापस की नाशक जब तक पैदा की धागा निष्पादन (§30.6.8 [वायदा पूरा करता ब्लॉक करने के लिए आवश्यक है।async]/पी 5):

कार्यान्वयन चुनता है launch::async नीति,

  • [...]
  • जुड़े धागा पूरा होने साथ (1.10) से वापसी सिंक्रनाइज़ करता है पहला फ़ंक्शन जो साझा स्थिति के स्थिति को सफलतापूर्वक पता लगाता है या अंतिम फ़ंक्शन से वापस लौटाता है जो साझा स्थिति को जारी करता है, जो भी पहले होता है।

इस मामले में, future के नाशक "पिछले समारोह है कि साझा राज्य विज्ञप्ति" है, इसलिए धागा पूरा होने सिंक्रनाइज़ करना होगा साथ है (यानी, पहले हो) कि समारोह की वापसी।

+0

+1 एमएस ने एक अनुक्रम गिनती के बारे में गलत तरीके से +1 किए गए वीएस -2010 रेगेक्स बग के साथ कुछ ऐसा किया। नतीजा यह था कि उस विशिष्ट सुविधा के साथ अपने रेगेक्स का उपयोग करना था जिसे आपको अपनी अभिव्यक्ति को "तोड़ना" था, इसलिए यह उनके कार्यान्वयन के साथ "काम किया" था, लेकिन हकीकत में * गलत * अभिव्यक्ति थी और इसलिए कहीं और काम नहीं करेगा। जैसा कि आप कल्पना कर सकते हैं, एसएस 1 में इसे ठीक करने के लिए एमएस का निर्णय नहीं है, हालांकि उन्हें इसके बारे में पता था कि पहले से ही अच्छी तरह से प्राप्त नहीं हुआ था (लोग क्रोधित थे)। कम से कम यहां हम आपको भविष्य में एक चलने योग्य तरीके से लपेट सकते हैं जो विनाश पर '.wait()' को आमंत्रित करता है, इसलिए आपके पास व्यवहार्य विकल्प है। – WhozCraig

+0

लिंक के लिए धन्यवाद! इस बग के कारण बस दुर्घटनाग्रस्त हो गया। – Mikhail

0

मैं std :: भविष्य के प्रलेखन को देखा और std :: भविष्य के नाशक के लिए इस मिल गया है:

विज्ञप्ति किसी भी साझा राज्य। यह

  • का मतलब वापसी वस्तु या प्रदाता रखती है अपने साझा राज्य के लिए पिछले संदर्भ, साझा राज्य को नष्ट कर दिया जाता है; और
  • रिटर्न ऑब्जेक्ट या प्रदाता इसके साझा राज्य का संदर्भ देता है; और
  • ये क्रियाएं साझा स्थिति के लिए तैयार नहीं हो जाएंगी, सिवाय इसके कि यदि यह सभी सत्य हैं तो यह ब्लॉक हो सकता है: साझा स्थिति std :: async को कॉल द्वारा बनाई गई थी, साझा स्थिति है अभी तक तैयार नहीं है, और यह साझा राज्य का अंतिम संदर्भ था।

अंतिम बिंदु पर ध्यान दें। मेरी राय में आपको अपने दायरे के अंत में get पर कॉल करना होगा।

+0

'भविष्य के dtor' को ब्लॉक करना चाहिए यदि वह भविष्य' async' कॉल के माध्यम से अधिग्रहित किया गया था। वहां 'पाने' की कोई ज़रूरत नहीं है – ixSci

+0

@ixSci क्या यह भी मामला है यदि आप इसे std :: async के बिना करते हैं? – Franz

+0

नहीं, यह 'std :: async' कॉल के लिए विशेष है। हालांकि, यह बहुत भ्रमित है। लिंक @ टीसी देखें। मूल प्रश्न पर टिप्पणियों में पोस्ट किया गया। – ixSci

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